爲了不前端總體刷新,咱們採用ajax+iframe(兼容全部瀏覽器)上傳,這樣用戶上傳以後就能夠當即看到圖片:javascript
上傳前:html
上傳後:前端
前端部分html:java
<form style="display: inline-block" id="upload_img_form" name="form" action="/upload/" method="POST" enctype="multipart/form-data"> {% csrf_token %} <a id="fakeFile" class="fake-file"> <input type="file" name="img" onchange="UploadImage(this);"/> <input type="text" name="url" class="hide"/> </a> <iframe id='upload_img_iframe' name='upload_img_iframe' src="" class="hide"></iframe> </form>
別看這麼短短的html,坑卻很多:python
django竟然報錯了,筆者查了不少資料,最後才知道,原來,雖然url的最後沒有加'/',可是django在運行時會自動給url的後面加'/',所以,咱們在post提交時,必須在url的最後加'/'。ajax
MIDDLEWARE_CLASSES = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ]
django爲用戶實現防止跨站請求僞造的功能,經過中間件 django.middleware.csrf.CsrfViewMiddleware 來完成。而對於django中設置防跨站請求僞造功能有分爲全局和局部。數據庫
全局:django
中間件 django.middleware.csrf.CsrfViewMiddlewarejson
局部:瀏覽器
中間件'django.middleware.csrf.CsrfViewMiddleware',會查看post請求是否攜帶token ,若是沒有則直接在process_request中return 並報出以下錯誤:
此時,咱們有幾種處理方式:1.直接簡單粗暴的註釋掉settings中的csrf中間件;2.給接收post請求的views函數加@csrf_exempt(注:from django.views.decorators.csrf import csrf_exempt,csrf_protect),該裝飾器的意思是取消當前函數防跨站請求僞造功能;
JavaScript代碼:
function UploadImage(ths) { document.getElementById('upload_img_iframe').onload = UploadImageComplete; //頁面加載完成後執行UploadImageComplete函數 document.getElementById('upload_img_form').target = 'upload_img_iframe'; //設置form提交到iframe document.getElementById('upload_img_form').submit(); //#提交到iframe } function UploadImageComplete() { var origin = $("#upload_img_iframe").contents().find("body").text();//#獲取圖片數據 var obj = JSON.parse(origin); //#轉換成JavaScript對象 var img = document.createElement('img'); //#建立img標籤 img.src = obj.path; //圖片地址 img.style.width = "200px"; img.style.height = "180px"; $("#upload_img_form").append(img);//添加圖片 $('#fakeFile').addClass('hide'); $('#reUploadImage').removeClass('hide'); $('#fakeFile').find('input[type="text"]').val(obj.data);//#保存圖片地址到隱藏的input標籤中 }
後臺views函數代碼:
def upload(request): if request.method == 'POST': obj = request.FILES.get('img')#獲取圖片對象 pat = os.path.join('static','img','vote',obj.name)#文件打開目錄,須要和當前文件路徑一致 f = open(pat,'wb') for ch in obj.chunks(): f.write(ch) f.close() ret = {'path': '/'+os.path.join('static','img','vote',obj.name)}#django前端文件路徑:'/' + 靜態文件前綴static + 靜態文件下的目錄 import json return HttpResponse(json.dumps(ret))#反饋給前端 return render(request,'upload.html',)
後臺和前端js關於文件路徑再現一坑:
注:這裏咱們將圖片保存在靜態文件目錄static下的img中(靜態文件路徑的前綴也是static)
django前端咱們但願的引入圖片的路徑是這樣的:/static/img/xx.png,這裏須要注意的是static前必須加'/',沒錯,就是這個神奇的'/',表明當前程序主目錄,即配置文件中的BASE_DIR。
後臺咱們打開文件寫入圖片到服務器的路徑,這裏open路徑須要遵循的是python的規則而不是django前端的規則,即python會默認從當前路徑開始找,所以直接static/img/xx.png就行,前面不須要加'/'。
json不能序列化django中的datatime、Decimal等數據結構,解決方案:
1.單獨轉爲python數據結構
str( Decimal('12.36'))
而後經過json進行序列化。
2.直接將數據庫查詢結果QuerySet對象轉化爲列表,QuerySet看起來像列表
ret=list(QuerySet對象)
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 o.strftime('%Y-%m-%d %H:%M:%S') elif isinstance(field, date): return o.strftime('%Y-%m-%d') else: return json.JSONEncoder.default(self, field) # ds = json.dumps(d, cls=JsonCustomEncoder)
這是經過制定json.dumps序列化的類來實現的。
3.使用django的序列化工具serializers
from django.core import serializers ret = models.BookType.objects.all() data = serializers.serialize("json", ret)
總結:常見的form表單傳文件可能你們都會,所以本博文主要講述了ajax+iframe上傳文件中須要注意的一些問題,如需form上傳文件案例,可聯繫本人,謝謝!