热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

十、Django的文件上传

一、上传文件相关1.请求头ContentTypeContentType指的是请求体的编码类型,常见的类型共有3种:1.applicationxwwwformurlencoded最常

一、上传文件相关

  1. 请求头ContentType

ContentType指的是请求体的编码类型,常见的类型共有3种:

  1. application/x-www-form-urlencoded
    最常见的 POST 提交数据的方式了
    浏览器的原生 form 表单,如果不设置?enctype?属性,那么最终就会以 默认格式application/x-www-form-urlencoded 方式提交数据,ajax默认也是这个
    urlencoded是一种数据格式,
    比如:
    username=yang&password=123&csrfmiddlewaretoken=.......
    # 这样的一种格式,类似get请求提交数据的格式

        # 这样在后台,就可以通过request.POST,就可以直接拿到数据了
        
  2. multipart/form-data
    专门用来传输文件的消息格式,会把文件作为片段数据发送,而不是整个文件一起发送
  3. application/json
    告诉服务端消息主体是序列化后的 JSON 字符串
    之前给ajax传递数据,就是把字典写成了一个类似json类型的数据
    def login(request):
    ...
    ret = ‘{"code":0,"redirect_url":"/index/"}‘
    return HttpResponse(ret)

    在不加content_type=‘application/json‘时,传递过去的就是一个字符串
    def login(request):
    d1 = {"code":0,"redirect_url":"/index/"}
    import json
    d1_json = json.dumps(d1)
    return HttpResponse(d1_json,)

    success:function (res) {
     console.log(res,typeof res);
        # {"code": 0, "redirect_url": "/index/"} string
        ....
     }
    
    这个时候,就不方便我们后续的使用,我们期望还是能拿到一个字典(自定义对象的类型)

    使用content_type=‘application/json‘,ajax就会调用自己内部的反序列化机制,直接调用反序列化方法
    def login(request):
    d1 = {"code":0,"redirect_url":"/index/"}
    import json
    d1_json = json.dumps(d1)
    return HttpResponse(d1_json,content_type=‘application/json‘)

    success:function (res) {
     console.log(res,typeof res);
        # {code: 0, redirect_url: "/index/"} "object"
        ....
     }
    
    此时,ajax端不需要自己序列化,也拿到了object类型的对象,这是因为内部自动调用的
  4. application/json 在ajax端发送数据,我们如何在视图函数中应用

    $.ajax({
    url:‘{% url "data" %}‘,
    type:‘post‘,
    data:JSON.stringify({k1:‘v1‘,k2:‘v2‘}), # 序列化成字符串
    contentType:‘application/json‘, # 指定类型
    ....
    })

    3 此时再
    def data(request):
        print(request.POST)   # ,拿不到数据
        print(request.body)   # b'{"k1":"v1","k2":"v2"}',要从原始的数据拿
        return HttpResponse('ok')
    
    
    
    b'{"k1":"v1","k2":"v2"}'
  5. 总之:
    • 在django内部,对于content-type是application/x-www-form-urlencoded的,可以解析,通过request.POST.get()就能取值
    • 在django内部,对于content-type是application/json类型的,是不能解析的,需要再request.body中取原始的数据,再反序列化,才能拿到数据
    • content-type就是一个数据格式,后端针对不同的数据格式进行不同的解析,默认是urlencoded的,django可以解析
      技术图片
  6. JsonResponse

JsonResponse是HttpResponse的子类,专门用来生成JSON编码的响应

此时传递数据的时候,既不需要自己做序列化,也不需要指定content_type=‘application/json‘,只需要把数据直接放在JsonResponse里,就会自动帮你转换成json字符串,并且自动拼接content_type=‘application/json‘,

from django.http import JsonResponse  # 需要先导入

def login(request):
    d1 = {"code":0,"redirect_url":"/index/"}
    return JsonResponse(d1)
    # 注意:字典类型可以直接JsonResponse(d1),若不是字典,是列表等,就要JsonResponse(d1,safe=False)
    
success:function (res) {
    console.log(res,typeof res);
    # {code: 0, redirect_url: "/index/"} "object"
    ....
    }
    
此时,也仍然拿到了object类型的数据

例子:

需求:用户输入127.0.0.1:8000/home,通过路径返回home.html文件,home.html文件中用ajax从data路径得到数据,然后在自己页面显示成一个列表显示出来

# 配置路径:
    url(r'^home/', views.home,name='home'),
    url(r'^data/', views.data,name='data'),
    
# 视图views:
    def home(request):
        return render(request,'home.html')

    def data(request):
        # l1 = ['故人西辞黄鹤楼','烟花三月下扬州','孤帆远影碧空尽','唯见长江天际流']
        l1 = [11,22,33,44]
        return JsonResponse(l1,safe=False) # 列表要加safe
    
# home.html:
    
    可见,ajax通过异步请求,在data路径拿到了数据组成了li标签,然后放在了ul标签下。 自动拼接content_type='application/json',可以从网页的Network下的XHR观察出来,XHR下的请求就是ajax请求

    技术图片

    1. form表单上传文件

    2. 配置路径 url(r‘^upload/‘, views.upload,name=‘upload‘),
    3. 写html,就一个表单提交数据,文件提交的(input属性是type="file")

      {% csrf_token %}
      头像:
      用户名:

    4. 写视图函数
      def upload(request):
      if request.method == ‘GET‘:
      return render(request,‘upload.html‘)
      else:
      print(request.POST)
      # 拿到的是post请求的数据,文件相关数据去request.FILES拿
      return HttpResponse(‘ok‘)

      打印的request.POST,数据如下:
      

      从得到的数据可以发现,request.POST得到的文件数据就是一个名字,没有任何意义

    5. 文件的数据,都在request.FILES中
      # 在form表单里,要先指定消息格式
      # 默认的请求消息格式是urlencoded,携带不了文件数据
      # 要指定multipart/form-data才可以携带数据

      ......

      def upload(request):
          if request.method == 'GET':
              return render(request,'upload.html')
          else:
              print(request.FILES)
              return HttpResponse('ok')
      
      # 如果form表单没有指定文件的消息格式,接收不到数据,就得到一个空字典:
      
      
      # 此时再打印request.FILES就拿到了上传了文件的数据:
      ]}>
    6. 把得到的文件数据读取出来,并保存到本地
      def upload(request):
      if request.method == ‘GET‘:
      return render(request,‘upload.html‘)
      else:
      file_obj = request.FILES.get(‘head_pic‘)
      file_name = file_obj.name

              with open(file_name,'wb') as f:
                  for i in file_obj:
                      f.write(i)
              return HttpResponse('ok')
    7. 以上方法上传的文件没有指定路径,就直接保存在了项目的文件夹里;此时想要把上传的文件保存在指定的文件夹中,比如项目下的statics中的img文件夹中
      from ajax_pro import settings
      import os

      def upload(request):
          if request.method == 'GET':
              return render(request,'upload.html')
          else:
      
              file_obj = request.FILES.get('head_pic')
              file_name = file_obj.name
      
              path = os.path.join(settings.BASE_DIR,'statics','img',file_name)
              # 拼接路径
              with open(path,'wb') as f:
                  for i in file_obj:
                      f.write(i) 
                      # 每次读的文件不是固定长度,每次读一行,识别符为\r,\n,,\r\n,遇到这几个符号就算是读了一行
      
              return HttpResponse('ok')
    8. 另一种保存文件的方法:
      from ajax_pro import settings
      import os

      def upload(request):
          if request.method == 'GET':
              return render(request,'upload.html')
          else:
      
              file_obj = request.FILES.get('head_pic')
              file_name = file_obj.name
      
              path = os.path.join(settings.BASE_DIR,'statics','img',file_name)
              # 拼接路径
              with open(path,'wb') as f:
                  for chunck in file_obj.chunks():
                      f.write(chunck) 
                      # 固定长度读取,默认一次读65536B,也就是64KB,2.5M,是一个生成器
      
              return HttpResponse('ok')
    9. ajax上传文件

    如何获取当前文件对象的数据:$(‘#file‘)[0].files[0]

    技术图片

    后端的读取文件并保存的代码跟form的文件上传一样

    前端的html文件,用到ajax

    ajax上传头像:
    ajax用户名:
    
    
    {% csrf_token %}
    
    
    

    根据以前写ajax代码的习惯,会这样写,但是会报错,因为文件上传要依靠FormData这个工具

    正确写法:

    ajax上传头像:
    ajax用户名:
    
    
    {% csrf_token %}
    
    
    

    注意点:

    • ajax文件上传需要借助FormData,给它填键值对的方式传输数据
    • data直接传formdata,但是后面要加processData:false和contentType:false
    1. JSON 机制
    • JSON 指的是 Javascript 对象表示法(Javascript Object Notation)
    • JSON 是轻量级的文本数据交换格式
    • JSON 独立于语言 *
    • JSON 具有自我描述性,更易理解

    技术图片

    json和python数据类型对比:

    技术图片

    但是,json在转换时间类型的时候,会出现问题:

    import datetime
    import json
    
    d = {'name':'yang','birthday':datetime.datetime.now()}
    json_str = json.dumps(d)
    
    print(json_str)
    
    # 报错,TypeError: Object of type 'datetime' is not JSON serializable,意思是'datetime'类型的是不能序列化的

    json序列化时间日期类型的数据的方法

    from datetime import date,datetime
    import json
    
    #对含有日期格式数据的json数据进行转换
    class JsonCustomEncoder(json.JSONEncoder):
        # 序列化的功能就是json.JSONEncoder这个类做的,因为它不能序列化时间,所以继承他的情况下进行拓展
        def default(self, field):
            if isinstance(field,datetime):
                # 如果是datetime类型的,返回一个datetime类型的字符串格式化输出
                return field.strftime('%Y-%m-%d %H:%M:%S')
            elif isinstance(field,date):
                # 如果是date类型的,返回一个date类型的字符串格式化输出
                return field.strftime('%Y-%m-%d')
            else:
                # 如果不是date、datetime类型的,就用父类的方法
                return json.JSONEncoder.default(self,field)
    
    
    d1 = datetime.now()
    json_str = json.dumps(d1,cls=JsonCustomEncoder)
    print(json_str)  # "2019-07-29 21:08:25"

    十、Django的文件上传


    推荐阅读
    • 通过优化模板消息机制,本研究提出了一种高效的信息化推送方案。该方案利用获取的访问令牌(access token)和指定的模板ID,实现了精准且快速的信息推送,显著提升了用户体验和信息传递效率。具体实现中,通过调用相关API接口,确保了消息的准确性和及时性,为用户提供更加便捷的服务。 ... [详细]
    • Django框架下的对象关系映射(ORM)详解
      在Django框架中,对象关系映射(ORM)技术是解决面向对象编程与关系型数据库之间不兼容问题的关键工具。通过将数据库表结构映射到Python类,ORM使得开发者能够以面向对象的方式操作数据库,从而简化了数据访问和管理的复杂性。这种技术不仅提高了代码的可读性和可维护性,还增强了应用程序的灵活性和扩展性。 ... [详细]
    • C#中实现高效UDP数据传输技术
      C#中实现高效UDP数据传输技术 ... [详细]
    • Spring Security 认证模块的项目构建与初始化
      本文详细介绍了如何构建和初始化Spring Security认证模块的项目。首先,通过创建一个分布式Maven聚合工程,该工程包含四个模块,分别为core、browser(用于演示)、app等,以构成完整的SeehopeSecurity项目。在项目构建过程中,还涉及日志生成机制,确保能够输出关键信息,便于调试和监控。 ... [详细]
    • PHP中元素的计量单位是什么? ... [详细]
    • 在ASP.NET MVC项目中,通过实战解决了Ajax请求500错误及多表数据查询的问题。具体而言,将页面分为两个部分,用户点击右侧导航栏时,通过Ajax请求动态加载数据,并在右侧显示相应的页面内容。最初尝试使用Partial Action方法,但遇到了500错误。通过详细排查和调试,最终成功解决了这一问题,并实现了预期功能。此外,还优化了多表数据查询的性能,确保系统的高效运行。 ... [详细]
    • 解决基于XML配置的MyBatis在Spring整合中出现“无效绑定语句(未找到):com.music.dao.MusicDao.findAll”问题的方法
      在将Spring与MyBatis进行整合时,作者遇到了“无效绑定语句(未找到):com.music.dao.MusicDao.findAll”的问题。该问题主要出现在使用XML文件配置DAO层的情况下,而注解方式配置则未出现类似问题。作者详细分析了两个配置文件之间的差异,并最终找到了解决方案。本文将详细介绍问题的原因及解决方法,帮助读者避免类似问题的发生。 ... [详细]
    • 本文详细探讨了Java集合框架的使用方法及其性能特点。首先,通过关系图展示了集合接口之间的层次结构,如`Collection`接口作为对象集合的基础,其下分为`List`、`Set`和`Queue`等子接口。其中,`List`接口支持按插入顺序保存元素且允许重复,而`Set`接口则确保元素唯一性。此外,文章还深入分析了不同集合类在实际应用中的性能表现,为开发者选择合适的集合类型提供了参考依据。 ... [详细]
    • 本文深入解析了 Apache 配置文件 `httpd.conf` 和 `.htaccess` 的优化方法,探讨了如何通过合理配置提升服务器性能和安全性。文章详细介绍了这两个文件的关键参数及其作用,并提供了实际应用中的最佳实践,帮助读者更好地理解和运用 Apache 配置。 ... [详细]
    • Spring Boot 实战(一):基础的CRUD操作详解
      在《Spring Boot 实战(一)》中,详细介绍了基础的CRUD操作,涵盖创建、读取、更新和删除等核心功能,适合初学者快速掌握Spring Boot框架的应用开发技巧。 ... [详细]
    • 本文深入探讨了ASP.NET中ViewState、Cookie和Session三种状态管理技术的区别与应用场景。ViewState主要用于保存页面控件的状态信息,确保在多次往返服务器过程中数据的一致性;Cookie则存储在客户端,适用于保存少量用户偏好设置等非敏感信息;而Session则在服务器端存储数据,适合处理需要跨页面保持的数据。文章详细分析了这三种技术的工作原理及其优缺点,并提供了实际应用中的最佳实践建议。 ... [详细]
    • 大数据应用实例:电视收视率分析企业项目实操第二篇
      本文继续探讨大数据在电视收视率分析中的应用,详细介绍了如何在CentOS系统中进行防火墙管理。针对CentOS 6.5及更早版本,提供了具体的命令操作步骤,包括停止防火墙服务和禁用防火墙启动。此外,还深入讨论了这些操作对数据传输和系统安全的影响,为实际项目实施提供了宝贵的技术参考。 ... [详细]
    • 我正在使用 Ruby on Rails 构建个人网站。总体而言,RoR 是一个非常出色的工具,它提供了丰富的功能和灵活性,使得创建自定义页面变得既高效又便捷。通过利用其强大的框架和模块化设计,我可以轻松实现复杂的功能,同时保持代码的整洁和可维护性。此外,Rails 的社区支持也非常强大,为开发过程中遇到的问题提供了丰富的资源和解决方案。 ... [详细]
    • 本文深入探讨了数据库性能优化与管理策略,通过实例分析和理论研究,详细阐述了如何有效提升数据库系统的响应速度和处理能力。文章首先介绍了数据库性能优化的基本原则和常用技术,包括索引优化、查询优化和存储管理等。接着,结合实际应用场景,讨论了如何利用容器化技术(如Docker)来部署和管理数据库,以提高系统的可扩展性和稳定性。最后,文章还提供了具体的配置示例和最佳实践,帮助读者在实际工作中更好地应用这些策略。 ... [详细]
    • 为了优化直播应用底部聊天框的弹出机制,确保在不同设备上的布局稳定性和兼容性,特别是在配备虚拟按键的设备上,我们对用户交互流程进行了调整。首次打开应用时,需先点击首个输入框以准确获取键盘高度,避免直接点击第二个输入框导致的整体布局挤压问题。此优化通过调整 `activity_main.xml` 布局文件实现,确保了更好的用户体验和界面适配。 ... [详细]
    author-avatar
    广东庚舞飞扬
    这个家伙很懒,什么也没留下!
    PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
    Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有