django练手(十九):图标上传页面增加浏览图标的功能

一、功能描述

  1. 图标上传后,可以直接在上传页面显示出来。

二、实现思路

  1. 增加一条路由,使django把识别uploads文件夹下的内容识别为静态文件。
  2. 把图标信息,图标路径从数据库中取出,返回前端,展示出来。
  3. 每次图标上传完成后,局部刷新图标展示的<div>,把所有图标展示出来。

三、功能实现

  1. bokeyuan-urls.py 文件中增加一条路由,路由的写法是:

     re_path(r'^uploads/(?P<path>.*)', serve, {"document_root": settings.MEDIA_ROOT}),
    
  2. 修改app-views-app-account.py 文件中的avatar_upload方法,在get方式访问的情况下,返回所用额图标信息

     @login_required
     def avatar_upload(request):
     	if request.method == 'GET':
     		# 获取所有的用户图标数据
     		avatars = Avatar.objects.filter().all
     		return render(request, 'app/user_info.html', {"avatars": avatars})
     	if request.method == "POST":
     		# 1、判断文件路径是否存在,如果不存在,生成文件路径。
     		image_folder_path = os.path.join(settings.MEDIA_ROOT, 'image', 'avatar')  # 文件路径
     		image_folder_path_exists = os.path.exists(image_folder_path)  # 判断文件路径是否存在
     		# 如果不存在,则生成文件路径
     		if not image_folder_path_exists:
     			os.makedirs(image_folder_path)
     		# 获取所有上传的图标
     		file_list = request.FILES.getlist('avatar_upload')
     		if file_list:
     			for file in file_list:
     				# 1、把文件名替换成整个系统唯一的文件名。
     				name = uuid_name(file.name)
     				# 2、获取文件中文名
     				title = os.path.splitext(file.name)[0]
     				# 3、文件存储的位置。
     				file_path = image_folder_path + '\\' + name
     				# 4、把文件写入硬盘
     				with open(file_path, 'wb', ) as f:
     					for part in file.chunks():
     						f.write(part)  # 内容块写入文件
     						f.flush()  # 清除内存
     				# 5、生成存储在数据库里的路径。
     				database_path = 'uploads/image/avatar/' + name
     				# 6、把文件信息写入数据库
     				avatar = Avatar()
     				avatar.title = title
     				avatar.img_url = database_path
     				avatar.save()
     				avatars = Avatar.objects.filter().all
     		return JsonResponse({"status": True,})
    
  3. 修改前端代码,增加两个功能:
    ①增加图片的显示位置。代码如下:

    <div class="row" id="avatar">
    		<div id="avatar_child" >
    			{% for avatar in avatars %}
    				<div class="col-xs-8 col-md-3">
    					<a href="#" class="thumbnail">
    						<img src="../../../{{ avatar.img_url }}" alt="{{ avatar.title }}">
    					</a>
    				</div>
    			{% endfor %}
    		</div>
    	</div>
    

    ②修改ajax代码,在上传动作完成后,增加刷新图片显示

    的功能。代码如下:

     $("#avatar_child").load(location.href+" #avatar_child>*","");
    

    ③完整的前端代码如下:

    {% extends 'app/layout/basic.html' %}
    
    {% block content %}
    	<!--
    	以下是图片显示的代码。
    	-->
    	<div class="row" id="avatar">
    		<div id="avatar_child" >
    			{% for avatar in avatars %}
    				<div class="col-xs-8 col-md-3">
    					<a href="#" class="thumbnail">
    						<img src="../../../{{ avatar.img_url }}" alt="{{ avatar.title }}">
    					</a>
    				</div>
    			{% endfor %}
    		</div>
    	</div>
    
    
    	<!--
    	上传文件的form。
    	action:后台的地址;
    	method:发送的方式。上传文件一般用post方式发送;
    	enctype:即encode type的缩写。意思是编码方式。 multipart/form-data 代表form数据有多种编码方式。
    	-->
    	<form name="file" method="post" action="{% url 'app:avatar_upload' %}" enctype="multipart/form-data"
    		  id="form_upload">
    		{% csrf_token %}
    		<!--
    		上传文件的input标签。
    		type的参数必须是file,代表上传文件。
    		accept表示允许上传的文件类型。"image/*"代表所用图片类型。
    		multiple 表示一次可以传多个文件。没有这个参数一次只能上传一个文件。
    		required 表示在提交前必须选择一个文件
    		-->
    		<input type="file" accept="image/*" name="avatar_upload" id="input_upload" multiple required>
    		<input type="button" value="上传" class="btn btn-default btn-custom" id="btn_upload">
    	</form>
    {% endblock %}
    {% block js %}
    	<script>
    		$("#btn_upload").click(
    			function () {
    				// 实例化一个FormData对象。这个对象包含form的内容。这个数据作为后面ajax上传的数据使用。
    				let formData = new FormData($("#form_upload")[0]);
    				// 获取input中上传的内容,类型为FileList
    				let files = $("#input_upload")[0].files;
    				// 定义一个数组,用来存储图片大小大于10000b的图片名称
    				let exceedArr = [];
    
    				// files.length==0,表示FileList的长度为0,即没有选择图片。则提示没有选择图片,否则通过ajax进行上传动作。
    				if (files.length === 0) {
    					alert("你没有选择图片");
    				} else {
    
    					//依次获取上传图片的大小,如果10000b,则把这个图片的名称存到数组里
    					for (let i = 0; i < files.length; i++) {
    						if (files[i].size > 40000) {
    							exceedArr.push(files[i].name);
    						}
    					}
    
    					/*
    					1、如果数组的长度大于0,则把数组中所用的图片名称拼接成一个字符串,并提示用户那些图片的大小超过了,同时清空文件选择控件。
    					2、如果数组的长度不大于0,则执行上传动作。上传完成后清空文件控件。
    					 */
    
    					if (exceedArr.length > 0) {
    						let alertStr = '';
    						for (let i = 0; i < exceedArr.length; i++) {
    							alertStr = alertStr + exceedArr[i] + ",";
    						}
    						alert(alertStr + " 大于10000b,请重新选择");
    						$("#input_upload").val("");
    					} else {
    						$.ajax({
    							url: "{% url 'app:avatar_upload' %}", //请求路径
    							type: 'POST', // 请求类型
    							data: formData, // 请求数据
    							dataType: "JSON", // 返回数据格式
    							contentType: false, //表示不处理数据
    							processData: false,//默认为true,表示会序列化数据。这里设置为false,表示不会序列化数据。
    							cache: false,
    							success: function (res) {
    								if(res.status){
    									$("#input_upload").val(""); //清空选择控件的内容
    									$("#avatar_child").load(location.href+" #avatar_child>*",""); //起局部刷新<div>的作用
    								}
    							},
    							error: function (res) {
    								console.log(res);
    							}
    						});
    					}
    				}
    			}
    		)
    	</script>
    {% endblock %}
    
    
posted @ 2024-01-10 12:47  喜气洋洋白云山  阅读(51)  评论(0编辑  收藏  举报