Django項(xiàng)目實(shí)戰(zhàn)之用戶頭像上傳與訪問的示例
1 將文件保存到服務(wù)器本地
upload.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> </head> <body> <form action="" method="post" enctype="multipart/form-data"> {% csrf_token %} <div>用戶名:<input type="text" name="username"></div> <div>頭像<input type="file" name="avatar"></div> <input type="submit" value="提交"> </form> </body> </html>
urls.py
from django.conf.urls import url from app01 import views urlpatterns = [ url(r'^upload',views.upload) ]
views.py
from django.shortcuts import render,HttpResponse def upload(request): if request.method == 'POST': name = request.POST.get('username') avatar = request.FILES.get('avatar') with open(avatar.name,'wb') as f: for line in avatar: f.write(line) return HttpResponse('ok') return render(request,'upload.html')
總結(jié)
這樣,我們就做好了一個(gè)基本的文件上傳小示例,這里需要注意的有幾點(diǎn):
1.form表單里需要加上csrf_token驗(yàn)證
2.文件的input框的type的值為file
3.在視圖函數(shù)中獲取文件要用request.FILES.get()方法
4.通過obj.name可以獲取文件的名字
2 將文件上傳到數(shù)據(jù)庫
models.py
from django.db import models class User(models.Model): username = models.CharField(max_length=16) avatar = models.FileField(upload_to='avatar')
views.py
def upload(request): if request.method == 'POST': name = request.POST.get('username') avatar = request.FILES.get('avatar') models.User.objects.create(username=name,avatar=avatar) return HttpResponse('ok') return render(request,'upload.html')
總結(jié)
上面已經(jīng)實(shí)現(xiàn)了將文件上傳到數(shù)據(jù)庫的功能,需要注意的有幾點(diǎn):
1.所謂的上傳到數(shù)據(jù)庫,不是講圖片本身或者二進(jìn)制碼放在數(shù)據(jù)庫,實(shí)際上也是將文件上傳到服務(wù)器本地,數(shù)據(jù)庫只是存了一個(gè)文件的路徑,這樣用戶要調(diào)用文件的時(shí)候就可以通過路徑去服務(wù)器指定的位置找了
2.創(chuàng)建ORM的時(shí)候,avatar字段要有一個(gè)upload_to=''的屬性,指定上傳后的文件放在哪里
3.往數(shù)據(jù)庫添加的時(shí)候,文件字段屬性賦值跟普通字段在形式上是一樣的,如:models.User.objects.create(username=name,avatar=avatar)
4.如果有兩個(gè)用戶上傳的文件名重復(fù),系統(tǒng)會(huì)自動(dòng)將文件改名,效果如下:
附加
功能我們是實(shí)現(xiàn)了,看起來我們在調(diào)用文件的時(shí)候,只需要通過數(shù)據(jù)庫文件路徑已經(jīng)保存的文件本身就可以訪問圖片,讓它出現(xiàn)在網(wǎng)頁上,其實(shí)并不是這樣,
我們需要配置一些東西,django才可以找的到,不然的話就會(huì)過不了urls驗(yàn)證,而我們之所以可以直接訪問static里的靜態(tài)文件,是因?yàn)閐jango已經(jīng)幫我們配置好了。
配置步驟如下:
1、在站點(diǎn)的setting.py里配置
MEDIA_ROOT=os.path.join(BASE_DIR,"blog","media") #blog是項(xiàng)目名,media是約定成俗的文件夾名 MEDIA_URL="/media/" # 跟STATIC_URL類似,指定用戶可以通過這個(gè)路徑找到文件
2、在urls.py里配置
from django.views.static import serve from upload import settings #upload是站點(diǎn)名 url(r'^media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),
配置完后,就可以通過http://127.0.0.1:8001/media/milk.png訪問到圖片了
3 用AJAX提交文件
upload.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> </head> <body> <form> {% csrf_token %} <div>用戶名:<input id="name-input" type="text"></div> <div>頭像<input id="avatar-input" type="file"></div> <input id="submit-btn" type="button" value="提交"> </form> <script src="/static/js/jquery-3.2.1.min.js"></script> <script> $('#submit-btn').on('click',function () { formdata = new FormData(); formdata.append('username',$('#name-input').val()); formdata.append("avatar",$("#avatar")[0].files[0]); formdata.append("csrfmiddlewaretoken",$("[name='csrfmiddlewaretoken']").val()); $.ajax({ processData:false,contentType:false,url:'/upload', type:'post', data:formdata,success:function (arg) { if (arg.state == 1){ alert('成功!') } else { alert('失敗!') } } }) }); </script> </body> </html>
views.py
from django.shortcuts import render,HttpResponse from django.http import JsonResponse from app01 import models def upload(request): if request.method == 'POST': name = request.POST.get('username') avatar = request.FILES.get('avatar') try: models.User.objects.create(username=name,avatar=avatar) data = {'state':1} except: data = {'state':0} return JsonResponse(data) return render(request,'upload.html')
總結(jié)
1.Ajax上傳的時(shí)候,按鈕的tpye一定不要用submit
2.Ajax上傳的時(shí)候data參數(shù)的值不再是一個(gè)普通‘字典'類型的值,而是一個(gè)FormData對(duì)像
- 創(chuàng)建對(duì)象formdata = new FormData();
- 往里面添加值formdata.append('username',$('#name-input').val());
3.Ajax在做post提交的時(shí)候要加上csrf驗(yàn)證
- formdata.append("csrfmiddlewaretoken",$("[name='csrfmiddlewaretoken']").val());
4.最后,Ajax上傳文件的時(shí)候要有兩個(gè)參數(shù)設(shè)置
- processData:false
- contentType:false
4 上傳圖片文件的時(shí)候有預(yù)覽功能
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> </head> <body> <form> <!----用一個(gè)label標(biāo)簽將上傳文件輸入框跟圖片綁定一起, 點(diǎn)擊圖片的時(shí)候就相當(dāng)于點(diǎn)擊了上傳文件的按鈕----> <label><img id="avatar-img" src="/static/img/default.png" width="80px" height="80px"> <div>頭像<input id="avatar-input" hidden type="file"></div> </label> <input id="submit-btn" type="button" value="提交"> </form> <script src="/static/js/jquery-3.2.1.min.js"></script> <script> // 上傳文件按鈕(label里的圖片)點(diǎn)擊事件 $('#avatar-input').on('change',function () { // 獲取用戶最后一次選擇的圖片 var choose_file=$(this)[0].files[0]; // 創(chuàng)建一個(gè)新的FileReader對(duì)象,用來讀取文件信息 var reader=new FileReader(); // 讀取用戶上傳的圖片的路徑 reader.readAsDataURL(choose_file); // 讀取完畢之后,將圖片的src屬性修改成用戶上傳的圖片的本地路徑 reader.onload=function () { $("#avatar-img").attr("src",reader.result) } }); </script>
5 大總結(jié)
對(duì)于文件上傳,不管是直接form提交也好,Ajax提交也好,根本問題是要告訴瀏覽器你要上傳的是一個(gè)文件而不是普通的字符串
而怎么樣告訴瀏覽器呢,就是通過請(qǐng)求體重的ContentType參數(shù),我們上傳普通的字符串的時(shí)候不用指定,因?yàn)樗心J(rèn)值,
而如果要傳文件的話,就要另外指定了??偨Y(jié)以下幾點(diǎn)
1.form表單上傳的話是通過 enctype="multipart/form-data" 來指定ContentType
2.ajax上傳的話是通過 processData:false 和 contentType:false來指定ContentType
3.form上傳的時(shí)候,文件數(shù)據(jù)是通過<input type="file">標(biāo)簽來‘'包裹‘'數(shù)據(jù),
4.ajax上傳的時(shí)候,是通過一個(gè) FormData 實(shí)例對(duì)象來添加數(shù)據(jù),傳遞的時(shí)候傳遞這個(gè)對(duì)象就行了
5.數(shù)據(jù)傳遞過去之后,是封裝在request.FILES里,而不是request.POST里
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Django中的JWT身份驗(yàn)證的實(shí)現(xiàn)
這篇文章主要介紹了Django中的JWT身份驗(yàn)證的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-05-05GitHub上值得推薦的8個(gè)python 項(xiàng)目
GitHub 無疑是代碼托管領(lǐng)域的先行者,Python 作為一種通用編程語言,已經(jīng)被千千萬萬的開發(fā)人員用來構(gòu)建各種有意思或有用的項(xiàng)目。以下我們會(huì)介紹一些使用 Python 構(gòu)建的GitHub上優(yōu)秀的項(xiàng)目。2020-10-10Python如何讀取txt文件,獲取指定行中指定位置數(shù)據(jù)
這篇文章主要介紹了Python如何讀取txt文件,獲取指定行中指定位置數(shù)據(jù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-03-03利用Python+eval函數(shù)構(gòu)建數(shù)學(xué)表達(dá)式計(jì)算器
Python?中的函數(shù)eval()?是一個(gè)非常有用的工具。在本文中,云朵君將和大家一起學(xué)習(xí)?eval()?如何工作,以及如何在?Python?程序中安全有效地使用它,需要的可以參考一下2022-09-09Python將xml和xsl轉(zhuǎn)換為html的方法
這篇文章主要介紹了Python將xml和xsl轉(zhuǎn)換為html的方法,實(shí)例分析了使用libxml2模塊操作xml和xsl轉(zhuǎn)換為html的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-03-03詳解利用裝飾器擴(kuò)展Python計(jì)時(shí)器
在本文中,云朵君將和大家一起了解裝飾器的工作原理,如何將我們之前定義的定時(shí)器類?Timer?擴(kuò)展為裝飾器,以及如何簡化計(jì)時(shí)功能,感興趣的可以了解一下2022-06-06