1. 程式人生 > >Django檔案上傳和圖片上傳

Django檔案上傳和圖片上傳

檔案上傳:

檔案上傳是網站開發中非常常見的功能。接下來就將詳細講述如何在Django中實現檔案的上傳功能。

前端HTML程式碼實現:

  1. 在前端中,我們需要填入一個form標籤,然後在這個form標籤中指定enctype=“multipart/form-data”,不然就不能上傳檔案。
  2. 在form標籤中新增一個input標籤,然後指定input標籤的name(即上傳檔案我們想要它顯示的名字),以及type=“file”。

新建一個file.html的檔案,body中寫入:

<form action="" method="post" enctype
="multipart/form-data">
<input type="file" name="myfile"> <input type="submit" value="提交"> </form>

後端的程式碼實現:

後端的主要工作是接收檔案。然後儲存檔案。接收檔案的方式跟接收POST的方式是一樣的,只不過是通過FILES來實現。示例程式碼如下:

在views中新增檢視函式:

from django.shortcuts import render
from django.views.generic import View
from
django.http import HttpResponse # Create your views here. class IndexView(View): def get(self,request): return render(request,'file.html') def post(self,request): myfile = request.FILES.get('myfile') with open('files.txt','wb') as fp: for chunk in myfile.
chunks(): fp.write(chunk) return HttpResponse('success')

然後在urls中新增對映,我們就可以執行專案了,
然後我們就可以選取本地的檔案進行上傳了。

使用模型來處理上傳的檔案:

在定義模型的時候,我們可以給儲存檔案的欄位指定為FileField,這個Field可以傳遞一個upload_to引數,用來指定上傳上來的檔案儲存到哪裡。比如我們讓他儲存到專案的files資料夾下,那麼示例程式碼如下:

在models中新建一個模型:

from django.db import models

# Create your models here.
class Article(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    file = models.FileField(upload_to='files')

因為我們指定了上傳到files資料夾中,所以我們需要手動在專案的根目錄下新建一個資料夾files,然後在檢視中新增檢視:

from .models import Article

class ArticleView(View):
    def get(self,request):
        return render(request,'file.html')
    def post(self,request):
        title = request.POST.get('title')
        content = request.POST.get('content')
        file = request.FILES.get('myfile')
        Article.objects.create(title=title,content=content,file=file)
        return HttpResponse('success')

這裡我們繼續渲染的時上面那個示例的模板,所以我們需要在上面的模板中新增兩個input標籤,在file.html中的body中寫入:

<form action="" method="post" enctype="multipart/form-data">
    <input type="text" name="title"><br>
    <input type="text" name="content"><br>
    <input type="file" name="myfile"><br>
    <input type="submit" value="提交"><br>
</form>

然後我們在urls中新增對映,就能夠正常的進行訪問了。

注意: 在資料庫中file欄位儲存的是檔案的路徑,而不是檔案的資訊。

指定MEDIA_ROOT和MEDIA_URL:

1. MEDIA_ROOT

上面我們是使用了upload_to來指定上傳的檔案的目錄。我們也可以指定MEDIA_ROOT,就不需要在FielField中指定upload_to,他會自動的將檔案上傳到MEDIA_ROOT的目錄下。

在settingsz.py中最下面新增程式碼:

# 指定上傳的檔案存放位置
MEDIA_ROOT = os.path.join(BASE_DIR,'media')
# 獲取上傳的檔案的url
MEDIA_URL = '/media/'

然後我們將上面的files資料夾修改一個檔名為media。並且可以將file欄位中的upload_to引數也去掉。

這樣,我們也能將檔案上傳至我們指定的media目錄下。

但是,這樣就產生了一個問題,隨著網站越來越大,那麼檔案上傳的次數肯定也多了,全部都放在media目錄下不方便我們管理。所以者惡搞時候我們可以對檔案儲存的位置進一步劃分。
我們在file欄位中繼續傳入一個引數upload_to

    file = models.FileField(upload_to='files')

這樣,因為我們在settings中設定了MEDIA_ROOT引數,所以Django會先去查詢MEDIA_ROOT引數中的值,然後再尋找upload_to中的值,所以最後上傳的檔案的路徑為media/files/< filename >

當然我們也可以按照時間來進行儲存,只需要改變upload_to的值就行了。

    file = models.FileField(upload_to='%Y/%m/%d/')

然後就會在media下生成一個年/月/日的資料夾。並且將我們上傳的檔案放入裡面。

2. MEDIA_URL

如果我們想要訪問上傳的檔案,那麼我們直接輸入網址

127.0.0.1:8000/media/<filename>

是訪問不到的,那麼我們應該怎樣來進行訪問呢。
這個時候我們就需要使用到MEDIA_URL了。

在主urls中新增程式碼

from django.urls import path,include

from django.conf.urls.static import static
# 匯入settings檔案,就能得到settings中的所有東西
from django.conf import settings

urlpatterns = [
    path('front/', include('front.urls')),
    path('file/',include('file.urls')),
] + static(settings.MEDIA_URL,document_root = settings.MEDIA_ROOT)

這樣,我們就可以像上面那樣輸入網址對檔案進行訪問了。

因為static函式返回的是一個列表,所以我們用+對他們進行連線,就會把static返回的列表中的值放入urlpatterns這個列表中。如果檔案時圖片也是一樣可以訪問的。

限制上傳的檔案拓展名:

為什麼我們需要限制上傳檔案的副檔名呢,因為如果別人上傳一些字尾名為.py、.php等檔案,那麼這些檔案是可以被執行的,那麼就對我們的網站存在著極大的安全隱患。所以我們需要限制檔案上傳的字尾名。

如果想要限制上傳的檔案的拓展名,那麼我們就需要用到表單來進行限制。我們可以使用普通的Form表單,也可以使用ModelForm,直接從模型中讀取欄位。

首先修改models中的程式碼,給file欄位新增一個validators

from django.db import models
from django.core import validators

# Create your models here.
class Article(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    # 只允許上傳txt檔案
    file = models.FileField(upload_to='%Y/%m/%d/',validators=[validators.FileExtensionValidator(['txt'],message='file必須為txt檔案')])

然後我們使用modelForm對資料進行驗證,新建一個forms.py檔案,寫入程式碼:


from django import forms
from .models import Article

class ArticleForm(forms.ModelForm):
    class Meta:
        model = Article
        fields = '__all__'

然後修改Views中的ArticleView檢視,將裡面的post函式註釋掉,然後重新寫入一個post函式

    def post(self,request):
        # request.POST,對普通欄位進行驗證
        # request.FILES 對檔案欄位進行驗證
        form = ArticleForm(request.POST,request.FILES)
        if form.is_valid():
            form.save()
            return HttpResponse('success')
        else:
            print(form.errors.get_json_data())
            return HttpResponse('fail')

因為我們使用的是modelForm,所以前端傳入資料的name屬性一定要和model中的欄位名一樣。所以我們修改file.html中的程式碼

<form action="" method="post" enctype="multipart/form-data">
    <input type="text" name="title"><br>
    <input type="text" name="content"><br>
{#    <input type="file" name="myfile"><br>#}
    <input type="file" name="file"><br>
    <input type="submit" value="提交"><br>
</form>

這樣,就完成了我們的程式碼,就可以輸入網址進行測試效果了。

上傳圖片:

上傳圖片跟上傳普通檔案是一樣的。只不過是上傳圖片的時候Django會判斷上傳的檔案是否是圖片的格式(除了判斷後綴名,還會判斷是否是可用的圖片)。如果不是,那麼就會驗證失敗。

這裡我們就修改models中的欄位就行了,就不去新增新的欄位了。

models中修改程式碼:

class Article(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    # 只允許上傳txt檔案
    # file = models.FileField(upload_to='%Y/%m/%d/',validators=[validators.FileExtensionValidator(['txt'],message='file必須為txt檔案')])
    # 上傳圖片
    file = models.ImageField(upload_to='%Y/%m/%d/')

forms中修改程式碼:

class ArticleForm(forms.ModelForm):
    class Meta:
        model = Article
        fields = '__all__'
        error_messages = {
            'cover':{
                'invalid_image':'請上傳正確格式的圖片~~',
            },
        }

然後就能對圖片進行上傳了,ImageField欄位在底層會幫我們進行驗證是否為可用的圖片,如果不是,就會返回錯誤。

注意: 使用ImageField,必須要先安裝Pillow庫:pip install pillow,如果安裝了pillow庫,仍然有錯誤的話,應該就是pillow庫版本過低,可以安裝指定的最新版本:
目前我的最新版本為5.3.0。可以輸入以下命令安裝

pip install pillow==5.3.0

想深入學習django的可以看一下這個視訊:超詳細講解Django打造大型企業官網