You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django如何实现文件仅上传存储到数据库 不保存到项目根目录

问题原因

你当前使用的Django原生FileField设计逻辑为:文件实体存储在文件系统中,数据库仅存储文件的访问路径。未给FileField指定upload_to参数时,文件默认会直接存储到项目根目录,因此出现你遇到的文件同时存在于磁盘和数据库的情况。

解决方案

核心思路是放弃使用FileField,改用BinaryField直接存储文件的二进制内容到数据库,同时新增字段存储文件名、文件类型等必要元数据,修改步骤如下:

1. 修改models.py

from django.db import models

class File(models.Model):
    file_name = models.CharField(max_length=255, blank=False, null=False)  # 存储原始文件名
    file_content = models.BinaryField(blank=False, null=False)  # 存储文件二进制内容
    file_type = models.CharField(max_length=100, blank=False)  # 存储文件MIME类型
    remark = models.CharField(max_length=20)
    timestamp = models.DateTimeField(auto_now_add=True)

注意:如果需要存储大于64KB的文件,需适配数据库的二进制字段上限,例如MySQL需修改字段类型为LONGBLOB。

2. 修改serializers.py

自定义序列化逻辑,将上传的文件读取为二进制后存入对应字段:

from rest_framework import serializers
from .models import File

class FileSerializer(serializers.ModelSerializer):
    # 仅用于接收上传文件,不直接映射到模型字段
    file = serializers.FileField(write_only=True)
    
    class Meta:
        model = File
        fields = ('file', 'remark', 'timestamp', 'file_name', 'file_type')
        read_only_fields = ('file_name', 'file_type', 'timestamp')
    
    def create(self, validated_data):
        uploaded_file = validated_data.pop('file')
        # 提取文件元数据和二进制内容
        validated_data['file_content'] = uploaded_file.read()
        validated_data['file_name'] = uploaded_file.name
        validated_data['file_type'] = uploaded_file.content_type
        return super().create(validated_data)

3. views.py无需修改

原有接口逻辑可以直接正常运行,不会再生成磁盘文件。

补充说明
  • 如果需要实现文件下载接口,只需从数据库取出file_content、file_name、file_type,设置对应HTTP响应头即可返回可下载的文件。
  • 该方案仅适合小文件存储场景,如果单文件大小超过10MB,更推荐使用对象存储服务存储文件实体,数据库仅存储文件访问地址,避免拖慢数据库性能。

内容的提问来源于stack exchange,提问作者Diego Donoso

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 15:36:06