Django FileField PUT更新时文件未保存到S3存储桶指定目录
问题定位
PUT请求更新文件时仅写入数据库文件名、文件未实际上传到S3,核心原因有两个:
- 自定义上传路径方法存在错误:代码中
f'{FILES_FOLDER}/{id}/{filename}'里的id是Python内置函数对象,不是实例的ID属性,POST创建场景下可能靠存储后端容错正常运行,PUT更新时路径生成异常直接中断S3上传流程 - DRF序列化器/视图逻辑错误:PUT更新时如果把上传的文件解析成了文件名字符串赋值给字段,没有传入真实文件对象,Django只会把字符串值写入数据库,不会触发文件上传逻辑
修复步骤
1. 修正上传路径生成方法
把路径里的id替换为实例的实际ID值,兼容实例未保存的场景,如果你的路径里需要的是自定义custom_id字段,直接替换对应字段名即可:
def upload_path_handler(instance, filename): # 优先取自定义ID,不存在则取主键ID target_id = getattr(instance, 'custom_id', instance.pk) return f'{FILES_FOLDER}/{target_id}/{filename}'
注意:如果用自增主键作为路径参数,POST创建时需要先保存实例拿到主键值,再关联文件,否则路径会出现None值
2. 修正序列化器字段配置
明确指定cc_file字段为文件类型,避免DRF自动将上传的文件解析为字符串:
from rest_framework import serializers from .models import YourModelClass class FileModelSerializer(serializers.ModelSerializer): cc_file = serializers.FileField(required=False, allow_null=True) class Meta: model = YourModelClass fields = '__all__'
3. 修正视图更新逻辑
PUT请求处理时,不要手动给cc_file字段赋值文件名字符串,直接从request.FILES中取文件对象赋值:
def update(self, request, *args, **kwargs): instance = self.get_object() # 禁止写 instance.cc_file = request.data.get('cc_file').name 这类逻辑 if 'cc_file' in request.FILES: instance.cc_file = request.FILES['cc_file'] serializer = self.get_serializer(instance, data=request.data, partial=kwargs.get('partial', False)) serializer.is_valid(raise_exception=True) self.perform_update(serializer) return Response(serializer.data)
4. (可选)配置旧文件自动清理
替换文件时自动删除S3上的旧文件,避免产生冗余存储:
from django.db.models.signals import pre_save from django.dispatch import receiver from .models import YourModelClass @receiver(pre_save, sender=YourModelClass) def auto_delete_old_s3_file(sender, instance, **kwargs): if not instance.pk: return old_record = sender.objects.filter(pk=instance.pk).first() if not old_record: return if old_record.cc_file and old_record.cc_file != instance.cc_file: old_record.cc_file.delete(save=False)
验证注意事项
- PUT请求上传文件时必须使用
multipart/form-data格式传参,文件参数名和字段名cc_file保持一致,不要把文件名作为普通字符串参数传递 - 保存后可通过
instance.cc_file.url确认生成路径正确,再到S3对应路径下核验文件是否存在
内容的提问来源于stack exchange,提问作者sk01
相关产品推荐
相关产品推荐

