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 {
            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="手動點擊上傳圖片">
        <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)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM