Django初窥门径-自定义附件存储模型

news2024/11/26 21:19:14

前言

Django自带了一个名为FileField的字段,用于处理文件上传。然而,有时我们需要更多的控制权,例如定义文件的存储路径、文件名以及文件类型。在本篇文章中,我们将探讨如何自定义Django附件存储模型。

创建attachment应用

python manage.py startapp attachment

然后,在项目的settings.py文件中,将应用注册到INSTALLED_APPS列表中,如下所示:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'drf_yasg2',
    'django_filters',
    'account.apps.AccountConfig',
    'oauth',
    'attachment'
]

创建模型

定义Attachment

from django.db import models

# Create your models here.
from rest_framework.reverse import reverse

from CodeVoyager.mixins import BaseModelMixin
import uuid


class BlobField(models.Field):
    description = 'Blob'

    def db_type(self, connection):
        return 'mediumblob'


class Attachment(BaseModelMixin):
    file_id = models.UUIDField(auto_created=True, default=uuid.uuid4, editable=False)
    file_name = models.CharField('文件名', max_length=200, unique=True)
    mime_type = models.CharField('MIME类型', max_length=100)
    file_size = models.PositiveIntegerField('文件长度')
    blob = BlobField('文件内容')

    class Meta:
        verbose_name = '附件'
        verbose_name_plural = verbose_name

    def get_url(self, request):
        return reverse('attachment:download', request=request, kwargs={'attachment_id': self.file_id})

字段名称类型用途
file_idUUIDField存储文件的唯一标识符
file_nameCharField存储文件的名称,即原始文件名
mime_typeCharField存储文件的MIME类型
file_sizePositiveIntegerField存储文件的大小(以字节为单位)
blob自定义 BlobField存储文件的二进制内容,即文件的实际数据

将更改应用到数据库

python manage.py makemigrations
python manage.py migrate

自定义Django存储

定义存储类

#!/usr/bin/python
# -*- coding: utf-8 -*-

from django.core.files.base import ContentFile, File
from django.core.files.storage import Storage
from django.utils.deconstruct import deconstructible


@deconstructible
class AttachmentStorage(Storage):
    """附件存储"""

    def __init__(self, model=None):
        from .models import Attachment
        self.model = Attachment

    def _open(self, file_id, mode='rb'):
        instance = self.model.objects.get(file_id=file_id)
        file = ContentFile(instance.blob)
        file.filename = instance.file_name
        file.mimetype = instance.mime_type
        return file

    def _save(self, name, content: File):
        blob = content.read()
        mime_type = getattr(content, 'content_type', 'text/plain')
        self.model.objects.create(
            file_name=name,
            blob=blob,
            file_size=content.size,
            mime_type=mime_type
        )
        return name

    def exists(self, name):
        return self.model.objects.filter(file_name=name).exists()


attachment_storage = AttachmentStorage()

方法名称参数返回值用途
_openfile_id, mode='rb'ContentFile打开文件以供读取,根据给定的file_idAttachment模型中获取文件记录并返回ContentFile对象。
_savename, content: File文件名保存文件,将文件名和文件内容作为参数,创建Attachment模型记录并将文件信息保存到数据库。
existsname布尔值 (TrueFalse)检查文件是否存在,根据给定的文件名查询Attachment模型,返回True如果文件存在,否则返回False

这些方法共同组成了AttachmentStorage类,用于处理附件文件的存储和访问。_open 方法用于读取文件,_save 方法用于保存文件,而exists 方法用于检查文件是否存在。请注意,初始化方法__init__接受一个model参数。

定义视图

上传视图

class AttachmentUploadView(APIView):
    permission_classes = (permissions.IsAdminUser,)

    def post(self, request, version):
        try:
            file = request.FILES['file']
        except MultiValueDictKeyError:
            raise ValidationError('参数错误')
        name = attachment_storage.save(file.name, file)
        attachment = get_object_or_404(Attachment, file_name=name)
        return JsonResponse({'download_url': attachment.get_url(request)}, status=status.HTTP_201_CREATED)
  • 作用:处理附件的上传操作。
  • 功能:当接收到POST请求时,该视图尝试从请求中获取名为 ‘file’ 的文件,然后使用自定义的存储后端 attachment_storage 来保存文件。接着,它在数据库中查找与文件名匹配的附件记录,并返回包含下载链接的 JSON 响应。这个视图的主要目的是允许用户上传附件,并提供上传后的附件的下载链接。

下载视图

class AttachmentDownloadView(APIView):
    permission_classes = (permissions.IsAuthenticated,)

    def get(self, request, version, attachment_id=None):
        attachment = attachment_storage.open(attachment_id)
        response = HttpResponse(attachment, content_type=attachment.mimetype)
        response['Content-Disposition'] = 'attachment;filename={name}'.format(name=attachment.filename).encode('utf-8')
        return response
  • 作用:处理附件的下载操作。
  • 功能:当接收到GET请求时,该视图使用传递的 attachment_id 参数来打开相应的附件。然后,它创建一个包含附件内容的 HTTP 响应对象,设置响应的内容类型为附件的 MIME 类型,并设置响应头 Content-Disposition,指定附件的文件名。最后,它返回包含附件内容的 HTTP 响应。这个视图的主要目的是允许用户通过提供附件的唯一标识符来下载附件。

Content-Disposition 是一个HTTP响应头,它用于指示浏览器如何处理接收到的文件。具体来说,Content-Disposition 头的值告诉浏览器应该如何处理响应的内容,通常用于文件下载操作。

注册视图

#!/usr/bin/python
# -*- coding: utf-8 -*-
from django.urls import re_path, path

from .views import AttachmentUploadView, AttachmentDownloadView

app_name = 'attachment'

urlpatterns = [
    re_path(r'upload', AttachmentUploadView.as_view(), name='upload'),
    path(r'download/<uuid:attachment_id>', AttachmentDownloadView.as_view(), name='download'),
]

使用swagger测试接口

上传

在这里插入图片描述

下载

在这里插入图片描述

结语

在开发Web应用程序时,文件上传和下载是常见的功能之一,但同时也需要特别关注安全性。通过合理的安全性配置,你可以保护应用程序和用户的数据免受潜在的威胁。在实际的项目中,我们可以增加一些重要的安全性措施,包括文件类型验证、文件大小限制、CSRF保护、存储路径安全性和其他关键措施,以确保文件上传和下载功能的安全性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1182558.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unity3d C#实现编辑器不运行状态下执行的脚本

第一章方式&#xff1a; 函数前面 [ContextMenu("Play")] &#xff0c;Inspector面板右键调用 第二种方式&#xff1a; OnValidate() &#xff0c;值改变自动执行 using UnityEngine; using System.Linq;public class NightController : MonoBehaviour {pub…

只需十分钟,快速入门Python3!

文章目录 前言1. 原始数据类型和运算符2. 变量和集合3. 流程控制和迭代器4. 函数5. 类6. 模块7. 高级用法关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②Python实战案例③Python小…

软考的好处 拥有软考证书的8大作用

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 1、软考证书认可度高 近年来《国家职业资格…

YOLOv5改进之CODConv,全维动态卷积再改进

目录 一、理论部分 网络结构 二、CODConv 代码 应用到YOLOv5中 一、理论部

本地生活餐饮视频怎么拍摄能有更多流量?如何批量生产呢?

本地生活近几年特别的火&#xff0c;所以到现在各类内容雷同性也比较高&#xff0c;视频缺少新的创意和玩法&#xff0c;像餐饮店的视频&#xff0c;大部分都是拍顾客进门、拍餐饮店座无虚席的实景……作为用户&#xff0c;其实早就已经看腻了。 今天推荐本地生活餐饮店商家拍…

旅游管理与推荐系统Python+Django网页平台+协同过滤推荐算法【计算机毕设项目】

一、介绍 旅游管理与推荐系统。本系统使用Python作为主要编程语言&#xff0c;前端采用HTML、CSS、BootStrap等技术实现界面展示平台的开发&#xff0c;后端使用Django框架处理用户响应请求&#xff0c;并使用Ajax等技术实现前后端的数据通信。本系统主要功能有&#xff1a; …

【ROS】Nav2源码之nav2_collision_monitor详解

【ROS】郭老二博文之:ROS目录 1、简介 nav2_collision_monitor碰撞监视器是一个节点,为机器人提供了一个额外的安全级别。 它使用来自传感器的数据,执行若干与避免碰撞相关的任务,绕过成本图和轨迹规划器,监测是否需要紧急停止或者减速。 2、安全行为 Collision Mon…

ARMday03(寄存器读写、栈、程序状态寄存器、软中断和异常、混合编程)

单寄存器内存读写指令 将一个寄存器中的数值写入到内存&#xff0c;或者从内存中读取数据放在某一个指定寄存器中 指令码和功能 1.向内存中写&#xff1a; str{条件码} 目标寄存器,[目标地址]&#xff1a;将目标寄存器的4字节数值写入到目标地址为首地址的空间中 strh{条件码…

0X03

红包题第二弹 看到源码里面的提示 ?cmdphpinfo(); 看到源码 kk 关键点就是有两个正则表达式 第一个 preg_match("/[A-Za-oq-z0-9$]/",$cmd) 第二个 preg_match("/\~|\!|\|\#|\%|\^|\&|\*|\(|\)|\&#xff08;|\&#xff09;|\-|\_|\{|\}|\[|\]|\|\&q…

【MySQL日志与备份篇】其他数据库日志

其他数据库日志 文章目录 其他数据库日志1. 概述1.1 日志类型1.2 日志的弊端 2. 慢查询日志(slow query log)3. 通用查询日志(general query log)4. 错误日志(error log)5. 二进制日志(bin log)5.1 参数5.2 查看日志5.3 格式5.3.1 STATEMENT模式 &#xff08;基于SQL语句的复制…

Web组件

开发者使用Vue、React等框架来使用及创建定制的组件&#xff0c;Web组件是浏览器原生支持的替代这些框架的特性&#xff0c;主要涉及相对比较新的三个Web标准。这些Web标准允许JS使用新标签扩展HTML&#xff0c;扩展后的标签就是自成一体的、可重用的UI组件。 1 HTML模版 Docu…

数据结构大体体系

逻辑结构 线性结构线性表一串珠子用线连起来&#xff0c;这就是典型的“线性存储结构”。每颗珠子之间的关系结构也很简单&#xff0c;包括头尾的话&#xff0c;它们最少有一个关系对象&#xff0c;而中间的珠子无论前后都只有一个关系对象&#xff0c;即 one-to-one栈队列字符…

webgoat-Sensitive Data Exposure 敏感信息泄露

insecure login不安全的登录 Encryption is a very important tool for secure communication 0x02 点击login&#xff0c;可以看到payload里的username和password&#xff0c;输入后点击submit即可。 这题的目的是说明&#xff0c;信息传输过程中需要加密&#xff0c;如不…

【C语言 | 符号】C语言中符号易出错的地方

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

一次简单的测试

文章现写的&#xff0c;部分内容有些着急 0x01 测试过程 开局登录框&#xff0c;没有测试SQL注入与XSS(菜鸟&#xff0c;测也测不出来。) 有system用户&#xff0c;尝试弱口令&#xff0c;无果&#xff01; 直接namp来一下子端口探测吧 发现有3306与8888 3306 mysql测试 88…

python 之异常处理结构

文章目录 常见的异常处理表现形式1. SyntaxError2. NameError3. TypeError4. IndexError5. KeyError6. ZeroDivisionError7. FileNotFoundErrortry……except …… 结构1. try 块2. except 块示例&#xff1a;多个except块try……except ……else 结构结构说明&#xff1a;示例…

注册电气工程师(供配电)专业考试大纲纯干货分享

1.法律法规与工程管理 1.1熟悉我国工程勘察设计中必须执行法律、法规的基本要求&#xff1b; 1.2熟悉了解工程勘察设计中必须执行建设标准强制性条文的概念&#xff1b; 1.3了解我国工程项目管理的基本概念和项目建设法人、项目经理、项目招标与投标、项目承包与分包等基本要素…

MySQL 数据目录和 InnoDB 表空间补充知识:详细结构

1. 数据目录 在Ubuntu下&#xff0c;MySQL的数据目录为/var/lib/mysql 1.1 数据库在文件系统中的表示 &#xff08;1&#xff09;创建数据库时&#xff0c;会在数据目录下创建一个与数据库名同名的子目录。&#xff08;除了information_schema这个系统数据外&#xff09; &…

AVS3:双向梯度修正BGC

双向梯度修正&#xff08;Bi-directional Gradient Correction&#xff0c;BGC&#xff09;是利用双向参考块间的差值对预测值进行修正的技术。 BGC仅用于双向预测CU&#xff0c;设两个方向得到的单向预测值分别为pred0和pred1&#xff0c;修正前的双向预测值为predBI&#xf…

看完这篇,医学小白也能轻松玩转文献查阅

对医学生而言&#xff0c;文献查询是写论文必不可少的一环。然而这实在是一件重要但又心累的事情。你是否每次查找文献&#xff0c;都感觉自己在进行无意义的重复劳动&#xff1b;一天下来全在搜索、下载、保存&#xff1b;搜索引擎给出的结果太多太杂&#xff0c;或者找不到全…