django练手(十九):图标上传页面增加浏览图标的功能
一、功能描述
- 图标上传后,可以直接在上传页面显示出来。
二、实现思路
- 增加一条路由,使django把识别uploads文件夹下的内容识别为静态文件。
- 把图标信息,图标路径从数据库中取出,返回前端,展示出来。
- 每次图标上传完成后,局部刷新图标展示的
<div>
,把所有图标展示出来。
三、功能实现
-
bokeyuan-urls.py 文件中增加一条路由,路由的写法是:
re_path(r'^uploads/(?P<path>.*)', serve, {"document_root": settings.MEDIA_ROOT}),
-
修改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,})
-
修改前端代码,增加两个功能:
①增加图片的显示位置。代码如下:<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 %}