最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

django上傳文件的三種方式

 更新時(shí)間:2021年04月29日 10:56:04   作者:大江狗  
本章將介紹Django上傳處理文件中需要考慮的重要事項(xiàng),并提供通過(guò)自定義表單和ModelForm上傳文件的示范代碼(附GitHub地址)。如果你的項(xiàng)目中需要用到文件上傳,你可以從本文中獲得靈感,簡(jiǎn)化你的開發(fā)。

Django文件上傳需要考慮的重要事項(xiàng)

文件或圖片一般通過(guò)表單進(jìn)行。用戶在前端點(diǎn)擊文件上傳,然后以POST方式將數(shù)據(jù)和文件提交到服務(wù)器。服務(wù)器在接收到POST請(qǐng)求后需要將其存儲(chǔ)在服務(wù)器上的某個(gè)地方。Django默認(rèn)的存儲(chǔ)地址是相對(duì)于根目錄的/media/文件夾,存儲(chǔ)的默認(rèn)文件名就是文件本來(lái)的名字。上傳的文件如果不大于2.5MB,會(huì)先存入服務(wù)器內(nèi)存中,然后再寫入磁盤。如果上傳的文件很大,Django會(huì)把文件先存入臨時(shí)文件,再寫入磁盤。

Django默認(rèn)處理方式會(huì)出現(xiàn)一個(gè)問(wèn)題,所有文件都存儲(chǔ)在一個(gè)文件夾里。不同用戶上傳的有相同名字的文件可能會(huì)相互覆蓋。另外用戶還可能上傳一些不安全的文件如js和exe文件,我們必需對(duì)允許上傳文件的類型進(jìn)行限制。因此我們?cè)诶肈jango處理文件上傳時(shí)必需考慮如下3個(gè)因素:

  • 設(shè)置存儲(chǔ)上傳文件的文件夾地址
  • 對(duì)上傳文件進(jìn)行重命名
  • 對(duì)可接受的文件類型進(jìn)行限制(表單驗(yàn)證)

注意:以上事項(xiàng)對(duì)于上傳圖片是同樣適用的。

Django文件上傳的3種常見(jiàn)方式

Django文件上傳一般有3種方式(如下所示)。我們會(huì)針對(duì)3種方式分別提供代碼示范。

  • 使用一般的自定義表單上傳,在視圖中手動(dòng)編寫代碼處理上傳的文件
  • 使用由模型創(chuàng)建的表單(ModelForm)上傳,使用form.save()方法自動(dòng)存儲(chǔ)
  • 使用Ajax實(shí)現(xiàn)文件異步上傳,上傳頁(yè)面無(wú)需刷新即可顯示新上傳的文件

Ajax文件上傳部分見(jiàn)Django與Ajax交互篇。

項(xiàng)目創(chuàng)建與設(shè)置

我們先使用django-admin startproject命令創(chuàng)建一個(gè)叫file_project的項(xiàng)目,然后cd進(jìn)入file_project, 使用python manage.py startapp創(chuàng)建一個(gè)叫file_upload的app。

我們首先需要將file_upload這個(gè)app加入到我們項(xiàng)目里,然后設(shè)置/media/和/STATIC_URL/文件夾。我們上傳的文件都會(huì)放在/media/文件夾里。我們還需要使用css和js這些靜態(tài)文件,所以需要設(shè)置STATIC_URL。

#file_project/settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'file_upload',# 新增
]

STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, "static"), ]

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

#file_project/urls.py
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static

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

創(chuàng)建模型

使用Django上傳文件創(chuàng)建模型不是必需,然而如果我們需要對(duì)上傳文件進(jìn)行系統(tǒng)化管理,模型還是很重要的。我們的File模型包括file和upload_method兩個(gè)字段。我們通過(guò)upload_to選項(xiàng)指定了文件上傳后存儲(chǔ)的地址,并對(duì)上傳的文件名進(jìn)行了重命名。

#file_upload/models.py
from django.db import models
import os
import uuid

# Create your models here.
# Define user directory path
def user_directory_path(instance, filename):
    ext = filename.split('.')[-1]
    filename = '{}.{}'.format(uuid.uuid4().hex[:10], ext)
    return os.path.join("files", filename)

class File(models.Model):
    file = models.FileField(upload_to=user_directory_path, null=True)
    upload_method = models.CharField(max_length=20, verbose_name="Upload Method")

注意:如果你不使用ModelForm,你還需要手動(dòng)編寫代碼存儲(chǔ)上傳文件。

URLConf配置

本項(xiàng)目一共包括3個(gè)urls, 分別對(duì)應(yīng)普通表單上傳,ModelForm上傳和顯示文件清單。

#file_upload/urls.py
from django.urls import re_path, path
from . import views

# namespace
app_name = "file_upload"

urlpatterns = [
    # Upload File Without Using Model Form
    re_path(r'^upload1/$', views.file_upload, name='file_upload'),

    # Upload Files Using Model Form
    re_path(r'^upload2/$', views.model_form_upload, name='model_form_upload'),

    # View File List
    path('file/', views.file_list, name='file_list'),

]

使用一般表單上傳文件

我們先定義一個(gè)一般表單FileUploadForm,并通過(guò)clean方法對(duì)用戶上傳的文件進(jìn)行驗(yàn)證,如果上傳的文件名不以jpg, pdf或xlsx結(jié)尾,將顯示表單驗(yàn)證錯(cuò)誤信息。關(guān)于表單的自定義和驗(yàn)證更多內(nèi)容見(jiàn)Django基礎(chǔ): 表單forms的設(shè)計(jì)與使用。

#file_upload/forms.py

from django import forms
from .models import File

# Regular form
class FileUploadForm(forms.Form):
    file = forms.FileField(widget=forms.ClearableFileInput(attrs={'class': 'form-control'}))
    upload_method = forms.CharField(label="Upload Method", max_length=20,
                                   widget=forms.TextInput(attrs={'class': 'form-control'}))
    def clean_file(self):
        file = self.cleaned_data['file']
        ext = file.name.split('.')[-1].lower()
        if ext not in ["jpg", "pdf", "xlsx"]:
            raise forms.ValidationError("Only jpg, pdf and xlsx files are allowed.")
        # return cleaned data is very important.
        return file

注意: 使用clean方法對(duì)表單字段進(jìn)行驗(yàn)證時(shí),別忘了return驗(yàn)證過(guò)的數(shù)據(jù),即cleaned_data。只有返回了cleaned_data, 視圖中才可以使用form.cleaned_data.get(‘xxx')獲取驗(yàn)證過(guò)的數(shù)據(jù)。

對(duì)應(yīng)一般文件上傳的視圖file_upload方法如下所示。當(dāng)用戶的請(qǐng)求方法為POST時(shí),我們通過(guò)form.cleaned_data.get('file')獲取通過(guò)驗(yàn)證的文件,并調(diào)用自定義的handle_uploaded_file方法來(lái)對(duì)文件進(jìn)行重命名,寫入文件。如果用戶的請(qǐng)求方法不為POST,則渲染一個(gè)空的FileUploadForm在upload_form.html里。我們還定義了一個(gè)file_list方法來(lái)顯示文件清單。

#file_upload/views.py

from django.shortcuts import render, redirect
from .models import File
from .forms import FileUploadForm, FileUploadModelForm
import os
import uuid
from django.http import JsonResponse
from django.template.defaultfilters import filesizeformat

# Create your views here.


# Show file list
def file_list(request):
    files = File.objects.all().order_by("-id")
    return render(request, 'file_upload/file_list.html', {'files': files})

# Regular file upload without using ModelForm
def file_upload(request):
    if request.method == "POST":
        form = FileUploadForm(request.POST, request.FILES)
        if form.is_valid():
            # get cleaned data
            upload_method = form.cleaned_data.get("upload_method")
            raw_file = form.cleaned_data.get("file")
            new_file = File()
            new_file.file = handle_uploaded_file(raw_file)
            new_file.upload_method = upload_method
            new_file.save()
            return redirect("/file/")
    else:
        form = FileUploadForm()

    return render(request, 'file_upload/upload_form.html', 
                  {'form': form, 'heading': 'Upload files with Regular Form'}
                 )

def handle_uploaded_file(file):
    ext = file.name.split('.')[-1]
    file_name = '{}.{}'.format(uuid.uuid4().hex[:10], ext)

    # file path relative to 'media' folder
    file_path = os.path.join('files', file_name)
    absolute_file_path = os.path.join('media', 'files', file_name)

    directory = os.path.dirname(absolute_file_path)
    if not os.path.exists(directory):
        os.makedirs(directory)

    with open(absolute_file_path, 'wb+') as destination:
        for chunk in file.chunks():
            destination.write(chunk)

    return file_path

注意:

  • handle_uploaded_file方法里文件寫入地址必需是包含/media/的絕對(duì)路徑,如果/media/files/xxxx.jpg,而該方法返回的地址是相對(duì)于/media/文件夾的地址,如/files/xxx.jpg。存在數(shù)據(jù)中字段的是相對(duì)地址,而不是絕對(duì)地址。
  • 構(gòu)建文件寫入絕對(duì)路徑時(shí)請(qǐng)用os.path.join方法,因?yàn)椴煌到y(tǒng)文件夾分隔符不一樣。寫入文件前一個(gè)良好的習(xí)慣是使用os.path.exists檢查目標(biāo)文件夾是否存在,如果不存在先創(chuàng)建文件夾,再寫入。

上傳表單模板upload_form.html代碼如下:

#file_upload/templates/upload_form.html
{% extends "file_upload/base.html" %}
{% block content %}
{% if heading %}
<h3>{{ heading }}</h3>
{% endif %}

<form action="" method="post" enctype="multipart/form-data" >
  {% csrf_token %}
  {{ form.as_p }}
 <button class="btn btn-info form-control " type="submit" value="submit">Upload</button>
</form>
{% endblock %} 

顯示文件清單模板file_list.html代碼如下所示:

# file_upload/templates/file_list.html
{% extends "file_upload/base.html" %}

{% block content %}
<h3>File List</h3>
<p> <a href="/file/upload1/" rel="external nofollow" >RegularFormUpload</a> | <a href="/file/upload2/" rel="external nofollow" >ModelFormUpload</a>
    | <a href="/file/upload3/" rel="external nofollow" >AjaxUpload</a></p>
{% if files %}
<table class="table table-striped">
    <tbody>
    <tr>
        <td>Filename & URL</td>
        <td>Filesize</td>
        <td>Upload Method</td>
    </tr>
    {% for file in files %}
    <tr>
        <td><a href="{{ file.file.url }}" rel="external nofollow" >{{ file.file.url }}</a></td>
        <td>{{ file.file.size | filesizeformat }}</td>
        <td>{{ file.upload_method }}</td>
    </tr>
    {% endfor %}
    </tbody>
</table>

{% else %}

<p>No files uploaded yet. Please click <a href="{% url 'file_upload:file_upload' %}" rel="external nofollow" >here</a>
    to upload files.</p>
{% endif %}
{% endblock %}

注意: 

  • 對(duì)于上傳的文件我們可以調(diào)用file.url, file.name和file.size來(lái)查看上傳文件的鏈接,地址和大小。
  • 上傳文件的大小默認(rèn)是以B顯示的,數(shù)字非常大。使用Django模板過(guò)濾器filesizeformat可以將文件大小顯示為人們可讀的方式,如MB,KB。

使用ModelForm上傳文件

使用ModelForm上傳是小編我推薦的上傳方式,前提是你已經(jīng)在模型中通過(guò)upload_to選項(xiàng)自定義了用戶上傳文件存儲(chǔ)地址,并對(duì)文件進(jìn)行了重命名。我們首先要自定義自己的FileUploadModelForm,由File模型重建的。代碼如下所示:

#file_upload/forms.py
from django import forms
from .models import File

# Model form
class FileUploadModelForm(forms.ModelForm):
    class Meta:
        model = File
        fields = ('file', 'upload_method',)
        widgets = {
            'upload_method': forms.TextInput(attrs={'class': 'form-control'}),
            'file': forms.ClearableFileInput(attrs={'class': 'form-control'}),
        }

    def clean_file(self):
        file = self.cleaned_data['file']
        ext = file.name.split('.')[-1].lower()
        if ext not in ["jpg", "pdf", "xlsx"]:
            raise forms.ValidationError("Only jpg, pdf and xlsx files are allowed.")
        # return cleaned data is very important.
        return file

使用ModelForm處理文件上傳的視圖model_form_upload方法非常簡(jiǎn)單,只需調(diào)用form.save()即可,無(wú)需再手動(dòng)編寫代碼寫入文件。

#file_upload/views.py

from django.shortcuts import render, redirect
from .models import File
from .forms import FileUploadForm, FileUploadModelForm
import os
import uuid
from django.http import JsonResponse
from django.template.defaultfilters import filesizeformat

# Create your views here.
# Upload File with ModelForm

def model_form_upload(request):
    if request.method == "POST":
        form = FileUploadModelForm(request.POST, request.FILES)
        if form.is_valid():
            form.save() # 一句話足以
            return redirect("/file/")
    else:
        form = FileUploadModelForm()

    return render(request, 'file_upload/upload_form.html', 
                  {'form': form,'heading': 'Upload files with ModelForm'}
                 )

模板跟前面一樣,這里就不展示了。

GitHub源碼地址

https://github.com/shiyunbo/django-file-upload-download

小結(jié)

本文提供并解讀了利用Django上傳文件的3種主要方式(一般表單上傳,ModelForm上傳和Ajax上傳)及示范代碼。

以上就是django上傳文件的三種方式的詳細(xì)內(nèi)容,更多關(guān)于django上傳文件的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Python反向傳播實(shí)現(xiàn)線性回歸步驟詳細(xì)講解

    Python反向傳播實(shí)現(xiàn)線性回歸步驟詳細(xì)講解

    回歸是監(jiān)督學(xué)習(xí)的一個(gè)重要問(wèn)題,回歸用于預(yù)測(cè)輸入變量和輸出變量之間的關(guān)系,特別是當(dāng)輸入變量的值發(fā)生變化時(shí),輸出變量的值也隨之發(fā)生變化?;貧w模型正是表示從輸入變量到輸出變量之間映射的函數(shù)
    2022-10-10
  • python3 實(shí)現(xiàn)自定義切片類為左閉右閉詳情

    python3 實(shí)現(xiàn)自定義切片類為左閉右閉詳情

    這篇文章主要介紹了python3 實(shí)現(xiàn)自定義切片類為左閉右閉詳情,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2021-12-12
  • python版百度語(yǔ)音識(shí)別功能

    python版百度語(yǔ)音識(shí)別功能

    這篇文章為大家詳細(xì)主要介紹了python版百度語(yǔ)音識(shí)別功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-07-07
  • Python操作列表常用方法實(shí)例小結(jié)【創(chuàng)建、遍歷、統(tǒng)計(jì)、切片等】

    Python操作列表常用方法實(shí)例小結(jié)【創(chuàng)建、遍歷、統(tǒng)計(jì)、切片等】

    這篇文章主要介紹了Python操作列表常用方法,結(jié)合實(shí)例形式總結(jié)分析了Python列表常見(jiàn)的創(chuàng)建、遍歷、統(tǒng)計(jì)、切片等操作技巧與相關(guān)注意事項(xiàng),需要的朋友可以參考下
    2019-10-10
  • 使用python庫(kù)xlsxwriter庫(kù)來(lái)輸出各種xlsx文件的示例

    使用python庫(kù)xlsxwriter庫(kù)來(lái)輸出各種xlsx文件的示例

    這篇文章主要介紹了使用python庫(kù)xlsxwriter庫(kù)來(lái)輸出各種xlsx文件的示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • 如何利用itertuples對(duì)DataFrame進(jìn)行遍歷

    如何利用itertuples對(duì)DataFrame進(jìn)行遍歷

    這篇文章主要介紹了如何利用itertuples對(duì)DataFrame進(jìn)行遍歷問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • Windows 下更改 jupyterlab 默認(rèn)啟動(dòng)位置的教程詳解

    Windows 下更改 jupyterlab 默認(rèn)啟動(dòng)位置的教程詳解

    這篇文章主要介紹了Windows 下更改 jupyterlab 默認(rèn)啟動(dòng)位置,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-05-05
  • Python實(shí)現(xiàn)的排列組合計(jì)算操作示例

    Python實(shí)現(xiàn)的排列組合計(jì)算操作示例

    這篇文章主要介紹了Python實(shí)現(xiàn)的排列組合計(jì)算操作,涉及Python數(shù)學(xué)運(yùn)算的相關(guān)函數(shù)與使用技巧,需要的朋友可以參考下
    2017-10-10
  • Python 冷門魔術(shù)方法小結(jié)

    Python 冷門魔術(shù)方法小結(jié)

    本文主要介紹了Python 冷門魔術(shù)方法小結(jié),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2025-04-04
  • 使用python爬取抖音app視頻的實(shí)例代碼

    使用python爬取抖音app視頻的實(shí)例代碼

    這篇文章主要介紹了使用python爬取抖音app視頻的實(shí)例代碼,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12

最新評(píng)論

清新县| 丹凤县| 彭山县| 金川县| 开鲁县| 通河县| 墨玉县| 喀什市| 乌拉特前旗| 和平区| 武冈市| 枣强县| 宜兴市| 安多县| 永平县| 江陵县| 宜兴市| 白城市| 固安县| 巩义市| 湖北省| 华蓥市| 三门县| 卓资县| 邯郸县| 济源市| 九江市| 扎兰屯市| 七台河市| 平山县| 江北区| 密山市| 宁强县| 军事| 上饶市| 彰化县| 邵东县| 连平县| 莫力| 黄梅县| 定日县|