• django文件上传和序列化


    django实现文件上传

    使用form表单上传文件

    • html页面
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            .img {
                width: 300px;
                height: 300px;
            }
        </style>
    </head>
    <body>
        <form id="myform" method="POST" action="/upload/" enctype="multipart/form-data">
            <input type="text" name="byd" id="byd" placeholder="请输入字符串">
    
            <input type="file" name="img" id="img" value="手动点击上传图片">
            <input type="submit" name="提交">
        </form>
     </body>
     </html>
    • django view配置
    import os
    import time
    import json
    
    stat = {'status':False,'data':None,'msg':None}
    def upload(request):
        if request.method == 'POST':
            try:
                user = request.POST.get('byd')
                img = request.FILES.get('img')
                img_path = os.path.join('static',img.name)
                f = open(img_path,'wb')
                for chunk in img.chunks():
                    f.write(chunk)
                    f.close()
                stat['status'] = True
                stat['data'] = img_path
            except Exception as e:
                stat['msg'] = str(e)
            finally:
                return HttpResponse(json.dumps(stat))
        else:
            return render(request,'upload.html')

    涉及的知识:

    • 1) 表单上传的文件对象存储在类字典对象request.FILES中,表单格式需为multipart/form-data
    • 2)request.FILES中的键来自于表单中的<input type="file" name="" />的name值:
    • 3)request.FILES中的值均为UploadedFile类文件对象。

    UploadedFile

    UploadedFile是类文件对象,具有以下方法和属性:
    
    UploadedFile.read()
    
    读取整个上传文件的数据,文件较大时慎用。
    
    UploadedFile.multiple_chunks(chunk_size=None)
    
    判断文件是否足够大,一般为2.5M
    
    UploadedFile.chunks(chunk_size=None)
    
    返回一个生成器对象,当multiple_chunks()为True时应该使用这个方法来代替read().
    
    UploadedFile.name
    
    上传文件的name。
    
    UploadedFile.size
    
    上传文件的大小。
    
    UploadedFile.content_type
    
    上传文件时的content_type报头,例如(e.g. text/plain or application/pdf). 
    
    UpladedFile.charset
    
    编码
    • 4) 存储上传的数据。注意上传的是二进制文件,所以需使用wb模式打开文件
    f = open(img_path,'wb')
    for chunk in img.chunks():
     f.write(chunk)
     f.close()

    使用django自带的Form处理上传文件

    form表单

    from django import forms
    class UploadFileForm(forms.Form):
      title = forms.CharField(max_length=50)
      file = forms.FileField()

    view函数

    from django.http import HttpResponseRedirect
    from django.shortcuts import render_to_response
    from somewhere import handle_uploader_file
    def upload_file(request):
      if request.method == 'POST':
         form = UploadFileForm(request.POST, request.FILES)
         if form.is_valid():
            handle_uploaded_file(request.FILES['file'])
            return HttpResponseRedirect('/success/url')
      else:
         form = UploadFileForm()
      return render_to_response('upload.html', {'form': form})

    使用html的form表单上传,当提交文件之后,本页面会刷新,如果要实现上传文件页面不刷新,需要使用强大的ajax

    使用ajax上传文件

    我们平时使用jquery的ajax方法做post上传,其实是调用了ajax原生的XMLHttpRequest来发送请求。原生的ajax 上传文件涉及到两个对象FormData和XMLHttpRequest,具体参数请点击这里:http://www.cnblogs.com/pycode/p/django02.html

    原生ajax http请求

    • html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        {{ crruent_time }}
        <input type="button" value="XMLHttpRequest按钮" onclick="XhrAjax();"/>
        <input type="button" value="XMLHttpRequest,FormData按钮" onclick="XhrAjaxForm();"/>
        <script>
            function XhrAjax(){
                var xhr = new XMLHttpRequest();
                xhr.onreadystatechange = function(){
                   // 只有服务器端返回数据时,处理请求
                    if(xhr.readyState == 4){
                        // 服务器端响应的内容已经接受完毕
                        console.log(xhr.responseText);
                    }
                };
                // GET请求
                //xhr.open('GET', '/xhr_ajax?p=123');
                //xhr.send();
                // POST请求
                xhr.open('POST', '/xhr_ajax/');
                // 设置请求头
                xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8');
                xhr.send("k1=v1;k2=v2");
            }
            function XhrAjaxForm(){
                var xhr = new XMLHttpRequest();
                xhr.onreadystatechange = function(){
                   // 只有服务器端返回数据时,处理请求
                    if(xhr.readyState == 4){
                        // 服务器端响应的内容已经接受完毕
                        console.log(xhr.responseText);
                    }
                };
                // GET请求
                //xhr.open('GET', '/xhr_ajax?p=123');
                //xhr.send();
                // POST请求
                xhr.open('POST', '/xhr_ajax/');
                // 设置请求头
                // xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset-UTF-8');
                var form = new FormData();
                form.append('user', 'alex');
                form.append('pwd', '123');
                xhr.send(form);
            }
        </script>
    </body>
    </html>
    • view视图
    def ajax(request):
        current_time = time.time()
        return render(request,'ajax.html',{'current_time':current_time})
    def xhr_ajax(request):
        print(request.POST)
        print(request.GET)
        return HttpResponse('ok')

    原生ajax的XmlHttpRequest相关方法:

    a. void open(String method,String url,Boolen async)
       用于创建请求
        
       参数:
           method: 请求方式(字符串类型),如:POST、GET、DELETE...
           url:    要请求的地址(字符串类型)
           async:  是否异步(布尔类型)
     
    b. void send(String body)
        用于发送请求
     
        参数:
            body: 要发送的数据(字符串类型)
     
    c. void setRequestHeader(String header,String value)
        用于设置请求头
     
        参数:
            header: 请求头的key(字符串类型)
            vlaue:  请求头的value(字符串类型)
     
    d. String getAllResponseHeaders()
        获取所有响应头
     
        返回值:
            响应头数据(字符串类型)
     
    e. String getResponseHeader(String header)
        获取响应头中指定header的值
     
        参数:
            header: 响应头的key(字符串类型)
     
        返回值:
            响应头中指定的header对应的值
     
    f. void abort()
     
        终止请求

    原生ajax的XmlHttpRequest对象的主要属性:

    a. Number readyState
       状态值(整数)
     
       详细:
          0-未初始化,尚未调用open()方法;
          1-启动,调用了open()方法,未调用send()方法;
          2-发送,已经调用了send()方法,未接收到响应;
          3-接收,已经接收到部分响应数据;
          4-完成,已经接收到全部响应数据;
     
    b. Function onreadystatechange
       当readyState的值改变时自动触发执行其对应的函数(回调函数)
     
    c. String responseText
       服务器返回的数据(字符串类型)
     
    d. XmlDocument responseXML
       服务器返回的数据(Xml对象)
     
    e. Number states
       状态码(整数),如:200、404...
     
    f. String statesText
       状态文本(字符串),如:OK、NotFound...

    使用原生ajax 上传文件

    • html
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form id="myform">
            <input type="text" name="byd" id="byd" placeholder="请输入字符串">
            <input type="file" name="img" id="img" value="手动点击上传图片">
        </form>
        <a href="javascript:void(0)" style="margin:20px 0 0 20px;background-color: #2aabd2;color: white;display: inline-block;" onclick="ajax_upload();">Ajax原生上传</a>
     </body>
     </html>
    • js
    function ajax_upload() {
      var form = new FormData();    
      var xhr = new XMLHttpRequest();
      var fileobj = document.getElementById('img').files[0];
      form.append('byd',document.getElementById('byd').value);
      form.append('img',fileobj);
      xhr.onreadystatechange = function(){
         // 只有服务器端返回数据时,处理请求
          if(xhr.readyState == 4){
              // 服务器端响应的内容已经接受完毕
              console.log(xhr.responseText);
          }
      };
      xhr.open('POST', '/upload/');
      xhr.send(form);
      
    }
    • view实图 同html form

    使用jquery上传文件

    • html文件
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form id="myform">
            <input type="text" name="byd" id="byd" placeholder="请输入字符串">
            <input type="file" name="img" id="img" value="手动点击上传图片">
        </form>
        <a href="javascript:void(0)" style="margin:20px 0 0 20px;background-color: #2aabd2;color: white;display: inline-block;" onclick="jquery_upload();">jquery上传</a>
     </body>
     </html>
    • js文件
    function jquery_upload() {
                //jquery和dom对象互相转换
                //jquery --> dom    jqueryobj[0]
                // dom--->jquery    $(domobj)
                var fileobj = $('#img')[0].files[0];   //先将jquery对象转换为dom对象
                var form = new FormData();
                form.append('byd',$('#byd').val());
                form.append('img',fileobj);
                $.ajax({
                    url:'/upload/',
                    type:'POST',
                    data:form,
                    processData:false,   //设置不对数据进行自处理,默认jquery会对上传的数据进行处理
                    contentType:false,   //设置不添加请求头的内容类型
                    success:function (arg) {
                        alert(arg)
                    }
    
                })
            }
    • view实图 同html form

    利用iframe使用伪ajax请求

    不论是jquey或原生ajax,对以前的浏览器版本(ie6)以前是不兼容的,所以,如果要兼容以前的浏览器,可以使用iframe伪造ajax请求来进行文件上传

    • html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            .img {
                 300px;
                height: 300px;
            }
        </style>
    </head>
    <body>
        <iframe name="myiframe" id="myiframe" style="display: none;"></iframe>
        <form id="myform" method="POST" action="/upload/" enctype="multipart/form-data" target="myiframe">
            <input type="text" name="byd" id="byd" placeholder="请输入字符串">
            <input type="file" name="img" id="img" value="手动点击上传图片">
            <input type="file" name="img" id="img2" value="自动上传图片" onchange="iframe_upload()">
            <input type="submit" name="提交">
        </form>
        <a href="javascript:void(0)" style="margin:20px 0 0 20px;background-color:peru;color: white;display: inline-block;" onclick="iframe_upload();">Iframe上传</a>
        
    </body>
    </html>
    • js
    function iframe_upload() {
                $('#content_img').find('img').remove();
                document.getElementById('myiframe').onload = callback;
                document.getElementById('myform').target = "myiframe";
                document.getElementById('myform').submit();
    
            }
            function callback() {
                var text = $('#myiframe').contents().find('body').text();
                var resault = JSON.parse(text);
                if (resault.status) {
                    var tag = document.createElement('img');
                    tag.className = 'img';
                    tag.src = "/" + resault.data;
                    $('#content_img').append(tag);
                } else {
                    alert(resault.msg)
                }
    
            }

    注意:
    1、需要设置iframe的name值与form的target属性值一样,意思就是把form表单上传文件的刷新转嫁到iframe里去了;

    2、form表单的enctype属性值必须设置成multipart/form-data,将文件转换成文件流供后端接收;

    django models对象queryset序列化

    关于Django中的序列化主要应用在将数据库中检索的数据返回给客户端用户,特别的Ajax请求一般返回的为Json格式。

    • serializers
    from django.core import serializers
     
    ret = models.BookType.objects.all()
     
    data = serializers.serialize("json", ret)
    • json.dumps
    import json
     
    #ret = models.BookType.objects.all().values('caption')
    ret = models.BookType.objects.all().values_list('caption')
     
    ret=list(ret)
     
    result = json.dumps(ret)

    由于json.dumps时无法处理datetime日期,所以可以通过自定义处理器来做扩展,如:

    import json 
    from datetime import date 
    from datetime import datetime 
       
    class JsonCustomEncoder(json.JSONEncoder): 
        
        def default(self, field): 
         
            if isinstance(field, datetime): 
                return field.strftime('%Y-%m-%d %H:%M:%S') 
            elif isinstance(field, date): 
                return field.strftime('%Y-%m-%d') 
            else: 
                return json.JSONEncoder.default(self, field) 
       
       
    ds = json.dumps(d, cls=JsonCustomEncoder)
  • 相关阅读:
    Echarts图表常用功能配置,Demo示例
    Markdown 语法笔记
    EasyUI 通过 Combobox 实现 AutoComplete 效果
    python PIL Image基本的图片拼接、圆形裁减、添加文字
    Fiddler高级用法—Fiddler Script抓取app网页json数据并保存
    python elasticsearch环境搭建
    利用brich实现文本层次聚类,将文本内容分类
    python发送邮件带附件
    python-docx生成word文档
    python-pygal画图
  • 原文地址:https://www.cnblogs.com/pycode/p/upload.html
Copyright © 2020-2023  润新知