首页 > 代码库 > django文件上传和序列化

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 osimport timeimport jsonstat = {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.5MUploadedFile.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 formsclass UploadFileForm(forms.Form):  title = forms.CharField(max_length=50)  file = forms.FileField()

 

view函数

from django.http import HttpResponseRedirectfrom django.shortcuts import render_to_responsefrom somewhere import handle_uploader_filedef 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=http://www.mamicode.com/"XMLHttpRequest按钮" onclick="XhrAjax();"/>    <input type="button" value=http://www.mamicode.com/"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=http://www.mamicode.com/"手动点击上传图片">    </form>    <a href=http://www.mamicode.com/"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=http://www.mamicode.com/"手动点击上传图片">    </form>    <a href=http://www.mamicode.com/"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 {            width: 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=http://www.mamicode.com/"手动点击上传图片">        <input type="file" name="img" id="img2" value=http://www.mamicode.com/"自动上传图片" onchange="iframe_upload()">        <input type="submit" name="提交">    </form>    <a href=http://www.mamicode.com/"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)

 

django文件上传和序列化