Django项目实战之用户头像上传与访问的示例

作者:人生不如戏 时间:2021-01-27 04:28:16 

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 url
from app01 import views
urlpatterns = [
 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项目实战之用户头像上传与访问的示例

附加

功能我们是实现了,看起来我们在调用文件的时候,只需要通过数据库文件路径已经保存的文件本身就可以访问图片,让它出现在网页上,其实并不是这样,

我们需要配置一些东西,django才可以找的到,不然的话就会过不了urls验证,而我们之所以可以直接访问static里的静态文件,是因为django已经帮我们配置好了。

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 serve
from 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="/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,HttpResponse
from django.http import JsonResponse
from app01 import models
def 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对像

  1. 创建对象formdata = new FormData(); 

  2. 往里面添加值formdata.append('username',$('#name-input').val());

3.Ajax在做post提交的时候要加上csrf验证

  1. formdata.append("csrfmiddlewaretoken",$("[name='csrfmiddlewaretoken']").val());

4.最后,Ajax上传文件的时候要有两个参数设置

  1. processData:false

  2. contentType:false

 4 上传图片文件的时候有预览功能


<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
</head>
<body>
<form>
 <!----用一个label标签将上传文件输入框跟图片绑定一起,
    点击图片的时候就相当于点击了上传文件的按钮---->
 <label><img id="avatar-img" src="/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="/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里

来源:http://www.cnblogs.com/fu-yong/p/8831218.html

标签:Django,头像,上传
0
投稿

猜你喜欢

  • Python的几种主动结束程序方式

    2022-10-12 14:39:25
  • 超半数中文网页一年内将“消失”

    2008-03-08 12:49:00
  • ThinkPHP学习笔记(一)ThinkPHP部署

    2023-09-09 12:42:16
  • 使用Python编写爬虫的基本模块及框架使用指南

    2021-08-21 17:45:19
  • 如何判断用户在某一页面逗留了多长时间?

    2010-01-18 20:48:00
  • Python 运行 shell 获取输出结果的实例

    2023-08-02 16:51:18
  • Python开发之迭代器&生成器的实战案例分享

    2021-03-18 17:34:33
  • 如何减少SQL Server死锁发生的情况

    2009-02-24 17:49:00
  • Python中Subprocess的不同函数解析

    2022-03-10 05:23:00
  • 如何检测用户第一次访问我的网站并显示友好信息?

    2009-11-25 20:33:00
  • python中slice参数过长的处理方法及实例

    2023-07-13 13:12:10
  • 10大实用web应用界面技术[译]

    2009-01-20 12:40:00
  • MySQL数据库配置技巧

    2009-03-06 14:32:00
  • 逐步讲解向Access数据库上传且显示图片

    2008-11-28 16:51:00
  • 为您解读CSS优先级

    2009-06-18 18:29:00
  • 用户分类浅谈

    2009-09-27 12:14:00
  • MYSQL各字段的长度是多少?

    2009-10-28 18:32:00
  • 用python记录运行pid,并在需要时kill掉它们的实例

    2023-07-31 17:30:18
  • python学习笔记之列表(list)与元组(tuple)详解

    2022-04-13 00:15:13
  • Python大数据量文本文件高效解析方案代码实现全过程

    2023-01-18 04:57:01
  • asp之家 网络编程 m.aspxhome.com