掌握Django文件处理:一步步构建上传功能

简介: 文件上传算是一种很常见的需求,几乎构建很多项目系统,以及插件都需要用到。通过上面例子可以看到django通过forms表单的形式灵活定义文件上传的页面,字段,以及数据库存储。在实际项目中我们还要考虑到安全性,包括检查文件大小(可通过FileField的max_length属性设置)、防止路径遍历攻击。还需注意服务器端的验证,比如检查文件类型、内容安全等。

创建模型

首先先进入我们的testsite项目下,打开members/models.py文件,先添加我们保存文件的数据模型:

class Document(models.Model):
    name = models.CharField(max_length=255)
    file = models.FileField(upload_to='uploads/')  # 'uploads/' 是文件上传的相对路径
    uploaded_at = models.DateTimeField(auto_now_add=True)

这里的文件存储目录可以自定义我们需要存储文件的目录,也可以在我们的 env文件 做配置,这里直接读取相应的配置 env字段 就可以了。


进入testsite根目录执行更新迁移文件命令,这一步前面有说到,是为了更新迁移文件。

py manage.py makemigrations

1717662538242.jpg

可以看到我们的migrations目录增加了新的迁移文件

1717662623475.jpg

执行迁移

py manage.py migrate

1717662659068.jpg

我们新增加的文件模型表就在数据库生成好了。

使用模型

进入testsite/members目录,新增form.py表单文件,这里会定义文件上传的字段。

from django import forms
from .models import Document

class UploadFileForm(forms.ModelForm):
    class Meta:
        model = Document
        fields = ['name', 'file']  # 包含你想要用户填写的字段

接下来将上传的文件绑定到表单中,打开testsite/members/views.py视图文件:

from .forms import UploadFileForm #需要我们引入上一步建立好的表单文件

def upload_file(request):
    if request.method == "POST":
        form = UploadFileForm(request.POST, request.FILES)
        if form.is_valid():
            form.save()  # 保存表单数据到数据库
            return HttpResponse("上传成功")
    else:
        form = UploadFileForm()
    return render(request, "polls/upload.html", {"form": form})

我们传递request.FILES 到表单的构造函数;这就是文件数据绑定到表单的方式。

请注意,request.FILES仅当请求方法为POST,实际发送了至少一个文件字段且<form>表单有发送请求的并且具有enctype="multipart/form-data"属性时。否则request.FILES将为空。

最后一步,添加上传页面,进入members/templates/members目录,新增upload.html文件,注意跟我们的视图里面指向的文件名保持一致。

<form method="post" enctype="multipart/form-data">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">提交</button>
</form>

打开地址http://127.0.0.1:8000/polls/upload/进入文件上传页面

1717662884066.jpg

点写完表单点击提交

1717662965221.jpg

这个时候我们的文件上传就完成了,可以打开我们的testsite目录,进入我们设置的uploads目录,就看到我们上传好的文件:

1717662996161.jpg

然后我们再打开数据库,进入模型对应的members_document表,也可以看到文件上传生成的数据。

1717663025674.jpg

批量上传

为了使用一个表单字段上传多个文件,创建该字段的子类并将其allow_multiple_selected类属性设置为True


进入表单文件forms.py

class MultipleFileInput(forms.ClearableFileInput):
    allow_multiple_selected = True

class MultipleFileField(forms.FileField):
    def __init__(self, *args, **kwargs):
        kwargs.setdefault("widget", MultipleFileInput())
        super().__init__(*args, **kwargs)

    def clean(self, data, initial=None):
        single_file_clean = super().clean
        if isinstance(data, (list, tuple)):
            result = [single_file_clean(d, initial) for d in data]
        else:
            result = [single_file_clean(data, initial)]
        return result

class FileFieldForm(forms.Form):
    file_field = MultipleFileField()

然后进入view.py视图文件重写子类form_valid()的方法 FormView来处理多个文件上传:

from .forms import FileFieldForm  # 确保导入正确的表单定义
from .models import Document  # 引入Document模型
def batch_upload_view(request):
    if request.method == 'POST':
        form = FileFieldForm(request.POST, request.FILES)
        if form.is_valid():
            # 获取表单中title的值
            title = form.cleaned_data['title']
            # 处理文件上传
            for file in request.FILES.getlist('file_field'):
                document = Document(file=file, name=title)  # 假设title作为文件的名称或描述
                document.save()

        return HttpResponse("上传成功")
    else:
        # 请求方法为GET时,初始化表单
        form = FileFieldForm()

    return render(request, "polls/uploads.html", {"form": form})

假如你不想使用模型关联上传,则使用如下方式:

from django.core.files.storage import default_storage
#使用默认存储引擎保存文件
file_name = default_storage.save(file.name, file)

然后重新渲染我们的批量上传页面,跟我们的forms django表单关联

<form method="post" enctype="multipart/form-data"> <!-- enctype 必须为 multipart/form-data 以支持文件上传 -->
    {% csrf_token %} <!-- Django表单必须的安全令牌 -->
    {{ form.title }} 
    {{ form.file_field }} <!-- 渲染文件上传字段,MultipleFileField将会生成相应的input元素 -->

    <button type="submit">上传文件</button>
</form>

上面的 csrf_token  django表单必须的安全令牌,form.file_field 也是我们form.py定义的批量上传字段。


打开members/urls.py,添加我们的路由

path('uploads/', views.batch_upload_view, name='upload'),

我们的批量上传功能就已经写好了,我们打开http://127.0.0.1:8000/polls/uploads/页面

1717663222668.jpg

填好表单,批量选择文件,点击上传,这里我只是演示,没有做页面渲染样式与字段验证,感兴趣的小伙伴可以加上自己喜欢的样式。

1717663245896.jpg

然后进入我们的数据库可以看到我们与上传模型的记录被添加

1717663269258.jpg

我们打开uploads目录,也可以看到我们上传好的文件。

1717663288157.jpg

需要注意的是在保存上传的文件之前,数据需要存储在某个地方。


默认情况下,如果上传的文件小于 2.5 MBdjango 会将上传的全部内容保存在内存中。


这意味着保存文件仅涉及从内存读取和写入磁盘,因此速度非常快。


但是,如果上传的文件太大,django 会将上传的文件写入存储在系统临时目录中的临时文件。


例如/tmp/tmpzfp6I6.upload。如果上传的文件足够大,您可以看到该文件的大小随着 django 将数据传输到磁盘而增长

总结

文件上传算是一种很常见的需求,几乎构建很多项目系统,以及插件都需要用到。


通过上面例子可以看到django通过forms表单的形式灵活定义文件上传的页面,字段,以及数据库存储。


在实际项目中我们还要考虑到安全性,包括检查文件大小(可通过FileFieldmax_length属性设置)、防止路径遍历攻击。


还需注意服务器端的验证,比如检查文件类型、内容安全等。


例子里面有提到,djangoFileSystemStorageDefaultStorage类提供了基本的文件存储管理。


自定义存储后端可以提供更多灵活性,如自定义文件命名规则、存储路径等,以避免文件名冲突和优化组织结构。


大量文件上传或下载也会影响应用性能。最好采用云存储服务、内容分发网络(CDN)、以及对静态和媒体文件的有效缓存策略,可以显著提升用户体验。


对于我们本地的存储策略,需要考虑上传文件的生命周期管理,包括旧文件的定期清理策略,以避免无限制增长占用存储空间。

相关文章
|
1月前
|
前端开发 JavaScript UED
探索Python Django中的WebSocket集成:为前后端分离应用添加实时通信功能
通过在Django项目中集成Channels和WebSocket,我们能够为前后端分离的应用添加实时通信功能,实现诸如在线聊天、实时数据更新等交互式场景。这不仅增强了应用的功能性,也提升了用户体验。随着实时Web应用的日益普及,掌握Django Channels和WebSocket的集成将为开发者开启新的可能性,推动Web应用的发展迈向更高层次的实时性和交互性。
75 1
|
13天前
|
程序员 API 数据库
Django/Flask深度揭秘:揭秘那些让程序员爱不释手的神奇功能!
在Web开发领域,Django与Flask凭借其独特魅力和强大功能深受程序员喜爱。Django作为全能型框架,以其ORM、模板引擎和丰富的内置功能著称;Flask则以轻量级、灵活的路由系统和强大的扩展生态见长。两者各具特色,为开发者提供了高效、灵活的开发工具。
36 4
|
1月前
|
开发框架 前端开发 数据库
使用Django框架构建一个完整的Web应用
【10月更文挑战第2天】使用Django框架构建一个完整的Web应用
32 1
|
1月前
|
存储 Python
使用django构建一个多级评论功能
使用django构建一个多级评论功能
20 0
|
1月前
|
监控 应用服务中间件 网络安全
部署Django应用:使用Gunicorn和Nginx构建高效的生产环境
部署Django应用:使用Gunicorn和Nginx构建高效的生产环境
105 0
|
3月前
|
存储 关系型数据库 MySQL
基于python django 医院管理系统,多用户功能,包括管理员、用户、医生,数据库MySQL
本文介绍了一个基于Python Django框架开发的医院管理系统,该系统设计了管理员、用户和医生三个角色,具备多用户功能,并使用MySQL数据库进行数据存储和管理。
136 4
基于python django 医院管理系统,多用户功能,包括管理员、用户、医生,数据库MySQL
|
2月前
|
数据处理 Python
Django视图:构建动态Web页面的核心技术
Django视图:构建动态Web页面的核心技术
|
3月前
|
数据可视化 安全 前端开发
基于Django的美团药品数据分析与可视化系统,有多用户功能,可增删改查数据
本文介绍了一个基于Django框架开发的美团药品数据分析与可视化系统,该系统具备多用户功能,支持数据的增删改查操作,并采用MySQL、pandas、echarts和bootstrap技术栈,为用户提供了一个高效、安全且实用的药品数据管理和分析平台。
基于Django的美团药品数据分析与可视化系统,有多用户功能,可增删改查数据
|
3月前
|
JSON API 数据安全/隐私保护
哇塞!Django REST framework 太逆天啦!构建 API 服务从未如此轻松,你还不来试试?
【8月更文挑战第31天】Django REST framework(DRF)是基于Django框架的高效Web API开发工具,提供序列化、视图集、路由等功能,简化API构建流程。使用DRF可轻松实现数据的序列化与反序列化,并支持权限管理和认证机制以保障API安全。安装DRF只需通过`pip install djangorestframework`命令。要创建基本项目,先安装Django并创建新应用,定义模型、序列化器及视图集,最后配置路由。测试API时,可通过Postman发送HTTP请求验证功能。无论项目大小,DRF均能提供强大支持。
41 0
|
3月前
|
SQL 安全 算法
【惊险揭秘】Django高手的十大安全秘籍:如何从零构建坚不可摧的Web堡垒?
【8月更文挑战第31天】《Django安全性指南:构建安全Web应用的十大关键步骤》介绍了在使用Django框架开发Web应用时,如何通过十个关键步骤提升应用安全性。从使用HTTPS、设置CSRF保护到限制密码复杂度、防止SQL注入,文章详细阐述了每一步的具体实施方法及示例代码,帮助开发者构建更加安全可靠的Web应用。
36 0