我的编程空间,编程开发者的网络收藏夹
学习永远不晚

django上传文件的三种方式

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

django上传文件的三种方式

Django文件上传需要考虑的重要事项

文件或图片一般通过表单进行。用户在前端点击文件上传,然后以POST方式将数据和文件提交到服务器。服务器在接收到POST请求后需要将其存储在服务器上的某个地方。Django默认的存储地址是相对于根目录的/media/文件夹,存储的默认文件名就是文件本来的名字。上传的文件如果不大于2.5MB,会先存入服务器内存中,然后再写入磁盘。如果上传的文件很大,Django会把文件先存入临时文件,再写入磁盘。

Django默认处理方式会出现一个问题,所有文件都存储在一个文件夹里。不同用户上传的有相同名字的文件可能会相互覆盖。另外用户还可能上传一些不安全的文件如js和exe文件,我们必需对允许上传文件的类型进行限制。因此我们在利用Django处理文件上传时必需考虑如下3个因素:

  • 设置存储上传文件的文件夹地址
  • 对上传文件进行重命名
  • 对可接受的文件类型进行限制(表单验证)

注意:以上事项对于上传图片是同样适用的。

Django文件上传的3种常见方式

Django文件上传一般有3种方式(如下所示)。我们会针对3种方式分别提供代码示范。

  • 使用一般的自定义表单上传,在视图中手动编写代码处理上传的文件
  • 使用由模型创建的表单(ModelForm)上传,使用form.save()方法自动存储
  • 使用Ajax实现文件异步上传,上传页面无需刷新即可显示新上传的文件

Ajax文件上传部分见Django与Ajax交互篇。

项目创建与设置

我们先使用django-admin startproject命令创建一个叫file_project的项目,然后cd进入file_project, 使用python manage.py startapp创建一个叫file_upload的app。

我们首先需要将file_upload这个app加入到我们项目里,然后设置/media/和/STATIC_URL/文件夹。我们上传的文件都会放在/media/文件夹里。我们还需要使用css和js这些静态文件,所以需要设置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)

创建模型

使用Django上传文件创建模型不是必需,然而如果我们需要对上传文件进行系统化管理,模型还是很重要的。我们的File模型包括file和upload_method两个字段。我们通过upload_to选项指定了文件上传后存储的地址,并对上传的文件名进行了重命名。


#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,你还需要手动编写代码存储上传文件。

URLConf配置

本项目一共包括3个urls, 分别对应普通表单上传,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'),

]

使用一般表单上传文件

我们先定义一个一般表单FileUploadForm,并通过clean方法对用户上传的文件进行验证,如果上传的文件名不以jpg, pdf或xlsx结尾,将显示表单验证错误信息。关于表单的自定义和验证更多内容见Django基础: 表单forms的设计与使用。


#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方法对表单字段进行验证时,别忘了return验证过的数据,即cleaned_data。只有返回了cleaned_data, 视图中才可以使用form.cleaned_data.get(‘xxx')获取验证过的数据。

对应一般文件上传的视图file_upload方法如下所示。当用户的请求方法为POST时,我们通过form.cleaned_data.get('file')获取通过验证的文件,并调用自定义的handle_uploaded_file方法来对文件进行重命名,写入文件。如果用户的请求方法不为POST,则渲染一个空的FileUploadForm在upload_form.html里。我们还定义了一个file_list方法来显示文件清单。


#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/的绝对路径,如果/media/files/xxxx.jpg,而该方法返回的地址是相对于/media/文件夹的地址,如/files/xxx.jpg。存在数据中字段的是相对地址,而不是绝对地址。
  • 构建文件写入绝对路径时请用os.path.join方法,因为不同系统文件夹分隔符不一样。写入文件前一个良好的习惯是使用os.path.exists检查目标文件夹是否存在,如果不存在先创建文件夹,再写入。

上传表单模板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 %}

注意: 

  • 对于上传的文件我们可以调用file.url, file.name和file.size来查看上传文件的链接,地址和大小。
  • 上传文件的大小默认是以B显示的,数字非常大。使用Django模板过滤器filesizeformat可以将文件大小显示为人们可读的方式,如MB,KB。

使用ModelForm上传文件

使用ModelForm上传是小编我推荐的上传方式,前提是你已经在模型中通过upload_to选项自定义了用户上传文件存储地址,并对文件进行了重命名。我们首先要自定义自己的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方法非常简单,只需调用form.save()即可,无需再手动编写代码写入文件。


#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

小结

本文提供并解读了利用Django上传文件的3种主要方式(一般表单上传,ModelForm上传和Ajax上传)及示范代码。

以上就是django上传文件的三种方式的详细内容,更多关于django上传文件的资料请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

django上传文件的三种方式

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

struts2文件上传采用的三种方式分别是什么

本篇文章给大家分享的是有关struts2文件上传采用的三种方式分别是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。文件上传几乎是每个项目实现的一个必须的模块。上传就是将信息
2023-06-17

三种Node.js写文件的方式

本文分享了Node.js写文件的三种方式,具体内容和如下 1、通过管道流写文件采用管道传输二进制流,可以实现自动管理流,可写流不必当心可读流流的过快而崩溃,适合大小文件传输(推荐)var readStream = fs.createRead
2022-06-04

SpringMVC上传文件的两种方法

在该示例中,阐述了SpringMVC如何上传文件。1、上传页面upload.jsp
2023-05-30

Vue组件通信传递数据的三种方式

这篇文章主要介绍了Vue组件通信传递数据的三种方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
2023-05-17

django 用户上传文件media的存

1. 首先新建文件夹media  后在项目setting中具体配置:1 MEDIA_URL = '/media/'2 MEDIA_ROOT = os.path.join(BASE_DIR, 'media')  在 setting 中的 TE
2023-01-30

jsp 实现上传文件的两种方法

在用Java开发企业器系统的使用,特别是涉及到与办公相关的软件开发的时候,文件的上传是客户经常要提到的要求.因此有 一套很好文件上传的解决办法也能方便大家在这一块的开发.........[@more@]在用Java开发企业器系统的使用,特别
2023-06-03

Python+django实现简单的文件上传

今天分享一下Django实现的简单的文件上传的小例子。 步骤创建Django项目,创建Django应用设计模型处理urls.py 以及views.py设计模板,设计表单运行项目,查看数据库 下面我们就一起来分别完成每一个小部分吧。 创建项目
2022-06-04

阿里云上传文件到服务器一种便捷的方式

简介:本文将介绍如何使用阿里云平台上传文件到服务器,并重点介绍了几种常用的方法。一、阿里云对象存储服务OSS阿里云提供了对象存储服务OSS(ObiectStorageService),可以通过该服务实现文件上传至服务器的操作。使用OSS,用户只需要创建一个存储空间即可开始上传文件。在创建存储空间时,需要设置存储空间名称
阿里云上传文件到服务器一种便捷的方式
2023-12-29

Django修改端口号与地址的三种方式

Django是一个开放源代码的Web应用框架,由Python写成,下面这篇文章主要给大家介绍了关于Django修改端口号与地址的三种方式,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
2023-02-23

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录