Django项目实战之用户头像上传与访问的示例
框架(架构)  /  管理员 发布于 7年前   166
1 将文件保存到服务器本地
upload.html
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"></head><body><form action="" method="post" enctype="multipart/form-data"> {% csrf_token %} <div>用户名:<input type="text" name="username"></div> <div>头像<input type="file" name="avatar"></div> <input type="submit" value="提交"></form></body></html>
urls.py
from django.conf.urls import urlfrom app01 import viewsurlpatterns = [ url(r'^upload',views.upload)]
views.py
from django.shortcuts import render,HttpResponse def upload(request): if request.method == 'POST': name = request.POST.get('username') avatar = request.FILES.get('avatar') with open(avatar.name,'wb') as f: for line in avatar: f.write(line) return HttpResponse('ok') return render(request,'upload.html')
总结
这样,我们就做好了一个基本的文件上传小示例,这里需要注意的有几点:
1.form表单里需要加上csrf_token验证
2.文件的input框的type的值为file
3.在视图函数中获取文件要用request.FILES.get()方法
4.通过obj.name可以获取文件的名字
2 将文件上传到数据库
models.py
from django.db import models class User(models.Model): username = models.CharField(max_length=16) avatar = models.FileField(upload_to='avatar')
views.py
def upload(request): if request.method == 'POST': name = request.POST.get('username') avatar = request.FILES.get('avatar') models.User.objects.create(username=name,avatar=avatar) return HttpResponse('ok') return render(request,'upload.html')
总结
上面已经实现了将文件上传到数据库的功能,需要注意的有几点:
1.所谓的上传到数据库,不是讲图片本身或者二进制码放在数据库,实际上也是将文件上传到服务器本地,数据库只是存了一个文件的路径,这样用户要调用文件的时候就可以通过路径去服务器指定的位置找了
2.创建ORM的时候,avatar字段要有一个upload_to=''的属性,指定上传后的文件放在哪里
3.往数据库添加的时候,文件字段属性赋值跟普通字段在形式上是一样的,如:models.User.objects.create(username=name,avatar=avatar)
4.如果有两个用户上传的文件名重复,系统会自动将文件改名,效果如下:
附加
功能我们是实现了,看起来我们在调用文件的时候,只需要通过数据库文件路径已经保存的文件本身就可以访问图片,让它出现在网页上,其实并不是这样,
我们需要配置一些东西,django才可以找的到,不然的话就会过不了urls验证,而我们之所以可以直接访问static里的静态文件,是因为django已经帮我们配置好了。
配置步骤如下:
1、在站点的setting.py里配置
MEDIA_ROOT=os.path.join(BASE_DIR,"blog","media") #blog是项目名,media是约定成俗的文件夹名MEDIA_URL="/media/" # 跟STATIC_URL类似,指定用户可以通过这个路径找到文件
2、在urls.py里配置
from django.views.static import servefrom upload import settings #upload是站点名url(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),
配置完后,就可以通过http://127.0.0.1:8001/media/milk.png访问到图片了
3 用AJAX提交文件
upload.html
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"></head><body><form> {% csrf_token %} <div>用户名:<input id="name-input" type="text"></div> <div>头像<input id="avatar-input" type="file"></div> <input id="submit-btn" type="button" value="提交"></form><script src="https:static/js/jquery-3.2.1.min.js"></script><script> $('#submit-btn').on('click',function () { formdata = new FormData(); formdata.append('username',$('#name-input').val()); formdata.append("avatar",$("#avatar")[0].files[0]); formdata.append("csrfmiddlewaretoken",$("[name='csrfmiddlewaretoken']").val()); $.ajax({ processData:false,contentType:false,url:'/upload', type:'post', data:formdata,success:function (arg) { if (arg.state == 1){ alert('成功!') }else { alert('失败!') } } }) }); </script> </body> </html>
views.py
from django.shortcuts import render,HttpResponsefrom django.http import JsonResponsefrom app01 import modelsdef upload(request): if request.method == 'POST': name = request.POST.get('username') avatar = request.FILES.get('avatar') try: models.User.objects.create(username=name,avatar=avatar) data = {'state':1} except: data = {'state':0} return JsonResponse(data) return render(request,'upload.html')
总结
1.Ajax上传的时候,按钮的tpye一定不要用submit
2.Ajax上传的时候data参数的值不再是一个普通‘字典'类型的值,而是一个FormData对像
3.Ajax在做post提交的时候要加上csrf验证
4.最后,Ajax上传文件的时候要有两个参数设置
4 上传图片文件的时候有预览功能
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"></head><body><form> <!----用一个label标签将上传文件输入框跟图片绑定一起, 点击图片的时候就相当于点击了上传文件的按钮----> <label><img id="avatar-img" src="https:static/img/default.png" width="80px" height="80px"> <div>头像<input id="avatar-input" hidden type="file"></div> </label> <input id="submit-btn" type="button" value="提交"></form><script src="https:static/js/jquery-3.2.1.min.js"></script><script> // 上传文件按钮(label里的图片)点击事件 $('#avatar-input').on('change',function () { // 获取用户最后一次选择的图片 var choose_file=$(this)[0].files[0]; // 创建一个新的FileReader对象,用来读取文件信息 var reader=new FileReader(); // 读取用户上传的图片的路径 reader.readAsDataURL(choose_file); // 读取完毕之后,将图片的src属性修改成用户上传的图片的本地路径 reader.onload=function () { $("#avatar-img").attr("src",reader.result) } });</script>
5 大总结
对于文件上传,不管是直接form提交也好,Ajax提交也好,根本问题是要告诉浏览器你要上传的是一个文件而不是普通的字符串
而怎么样告诉浏览器呢,就是通过请求体重的ContentType参数,我们上传普通的字符串的时候不用指定,因为它有默认值,
而如果要传文件的话,就要另外指定了。总结以下几点
1.form表单上传的话是通过 enctype="multipart/form-data" 来指定ContentType
2.ajax上传的话是通过 processData:false 和 contentType:false来指定ContentType
3.form上传的时候,文件数据是通过<input type="file">标签来‘'包裹‘'数据,
4.ajax上传的时候,是通过一个 FormData 实例对象来添加数据,传递的时候传递这个对象就行了
5.数据传递过去之后,是封装在request.FILES里,而不是request.POST里
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
122 在
学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..123 在
Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..原梓番博客 在
在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..博主 在
佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..1111 在
佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
Copyright·© 2019 侯体宗版权所有·
粤ICP备20027696号