1. 程式人生 > >Django上傳檔案(.txt .php .py .jpg .pdf .doc所有型別的檔案原理都一樣)基本原理:

Django上傳檔案(.txt .php .py .jpg .pdf .doc所有型別的檔案原理都一樣)基本原理:



1、上傳檔案基本原理:
①、index.html檔案如下:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>檔案上傳頁</title>
</head>
<body>

{#enctype="multipart/form-data"檔案編碼方式,必須設定,否則檔案無法上傳#}
<form action="" method="post" enctype="multipart/form-data">
    <input type="file" name="myfile">
    <input type="submit" value="提交">
</form>

</body>
</html>

②、views.py檔案如下:
from django.http import HttpResponse
from django.shortcuts import render
from django.views.generic import View

自定義儲存檔案的方法
def save_file(file):
    with open('somefile.txt', 'wb') as fp:
        for chunk in file.chunks():
            fp.write(chunk)

class IndexView(View):
    # 如果是GET請求,直接渲染到上傳檔案頁面
    def get(self, request):
        return render(request, 'one/index.html')

    # 如果是POST請求,那麼將接收檔案的值
    def post(self, request):
        # 獲取前臺傳來的檔案
        myfile = request.FILES.get('myfile')
        # 呼叫自定義的save_file()方法,將檔案儲存到伺服器
        save_file(myfile)

        return HttpResponse("SUCCESS")
③、路由
urlpatterns = [
    path('', IndexView.as_view()),
]


2、使用Django模型來上傳的檔案:
①、index.html檔案如下:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>檔案上傳頁</title>
</head>
<body>

{#enctype="multipart/form-data"檔案編碼方式,必須設定,否則檔案無法上傳#}
<form action="" method="post" enctype="multipart/form-data">
    <input type="text" name="title">
    <input type="text" name="content">
    <input type="file" name="myfile">
    <input type="submit" value="提交">
</form>

</body>
</html>

②、models.py檔案:(使用FileField欄位)
from django.db import models

class Article(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    # upload_to引數,用來指定上傳上來的檔案儲存到哪裡
    myfile = models.FileField(upload_to="media")

③、views.py檔案:
from django.http import HttpResponse
from django.shortcuts import render

from django.views.generic import View

from one.models import Article


class IndexView(View):
    # 如果是GET請求,直接渲染到上傳檔案頁面
    def get(self, request):
        return render(request, 'one/index.html')

    # 如果是POST請求,那麼將接收檔案的值
    def post(self, request):
        title = request.POST.get('title')
        content = request.POST.get('content')
        # 獲取前臺傳來的檔案
        myfile = request.FILES.get('myfile')
        # 將資料儲存到資料庫
	# 呼叫完article.save()方法,就會把檔案儲存到files下面,並且會將這個檔案的路徑儲存到資料庫中
        article = Article(title=title, content=content, myfile=myfile)
        article.save()
        return HttpResponse("SUCCESS")

④、路由
urlpatterns = [
    path('', IndexView.as_view()),
]


3、MEDIA_ROOT和MEDIA_URL使用
在使用Django模型來上傳檔案的時候,我們使用upload_to引數,來指定上傳上來的檔案儲存到哪裡,
那麼我們還可以通過在settings.py裡設定MEDIA_ROOT,來代替upload_to引數:

MEDIA_ROOT:指定上傳上來的檔案儲存在哪裡,以後再使用FileField欄位時,就不用設定upload_to引數了
MEDIA_URL:指定上傳檔案的訪問路徑,在瀏覽器中輸入檔案的url地址,就能訪問檔案了
在settings.py設定如下:
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

# 設定檔案可以在瀏覽器中使用地址訪問 
MEDIA_URL = '/media/'   # 檔案訪問地址:http://127.0.0.1:8000/one(app名)/media/12.jpg
# 設定好MEDIA_URL後,還要去urls.py檔案中新增檔案的訪問路徑,內容如下:
from django.conf import settings
from django.conf.urls.static import static

from django.urls import path
from .views import *

urlpatterns = [
    path('', IndexView.as_view()),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

4、如何實現上傳檔案,自動按 年/月/日 資料夾分層
# setting裡設定了MEDIA_ROOT
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# 同事又設定了upload_to為:
myfile = models.FileField(upload_to="%Y/%m/%d/")

# 那麼上傳的檔案儲存目錄:media/2018/10/25/12.jpg,
如果也設定了MEDIA_URL訪問路徑是:http://127.0.0.1:8000/one/media/2018/10/25/12.jpg

5、限制上傳的檔案拓展名:
eg:只能上傳.txt .pdf的檔案(如果想要限制上傳的檔案的拓展名,那麼我們就需要使用表單來進行限制)
# ①setting,py檔案加入下面設定:
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

# ②urls.py檔案新增檔案的訪問路徑
from django.conf import settings
from django.conf.urls.static import static

from django.urls import path
from .views import *

urlpatterns = [
    path('', IndexView.as_view()),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

# ③在models.py檔案中進行限制上傳檔案型別
from django.core import validators
from django.db import models


class Article(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    # 使用validators.FileExtensionValidator驗證器來進行限制:
    myfile = models.FileField(upload_to="%Y/%m/%d/", 
           validators=[validators.FileExtensionValidator(['txt', 'pdf'],
	     message='myfile必須為txt,pdf格式的檔案')])

# ④新建表單forms.py檔案:
from django import forms  # 注意是django下的forms
from one.models import Article


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

# ⑤ views.py檔案如下:
from django.http import HttpResponse
from django.shortcuts import render

from django.views.generic import View
from one.forms import ArticleForm


class IndexView(View):
    # 如果是GET請求,直接渲染到上傳檔案頁面
    def get(self, request):
        return render(request, 'one/index.html')

    # 如果是POST請求,那麼將接收檔案的值
    def post(self, request):
        # 獲取前臺傳來的檔案,request.POST用來接收title和content,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")
# ⑥表單頁index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>檔案上傳頁</title>
</head>
<body>

{#enctype="multipart/form-data"檔案編碼方式,必須設定,否則檔案無法上傳#}
<form action="" method="post" enctype="multipart/form-data">
    <input type="text" name="title">
    <input type="text" name="content">
    <input type="file" name="myfile">
    <input type="submit" value="提交">
</form>

</body>
</html>