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
相关产品推荐
相关产品推荐

