Django自引用M2M关联记录同步上传文件实现方法
Django DRF 上传文件同步至关联记录实现方案
第一步:优化序列化器定义
原序列化器的save_documents_to_related_records字段属于业务逻辑字段,不存在于RecordDocument模型中,需要补充参数避免校验、序列化报错:
class RecordDocumentSerializer(serializers.ModelSerializer): # 标记为只写字段,设置非必填、默认关闭同步 save_documents_to_related_records = serializers.BooleanField(required=False, default=False, write_only=True) class Meta: model = RecordDocument fields = ( 'save_documents_to_related_records', 'file', 'record' )
第二步:实现APIView上传逻辑
在post方法中先完成序列化校验,校验通过后从validated_data中直接取出同步开关的取值,按业务逻辑处理关联记录的文件同步即可,完整代码如下:
from rest_framework.response import Response from rest_framework import status class RecordDocumentUploadView(APIView): def post(self, request, *args, **kwargs): serializer = RecordDocumentSerializer(data=request.data) serializer.is_valid(raise_exception=True) # 从校验后的数据中取出同步开关参数,模型无此字段需先弹出 save_to_related = serializer.validated_data.pop('save_documents_to_related_records') # 先保存当前记录对应的文档 current_doc = serializer.save() current_record = current_doc.record if save_to_related and current_record: # 取出所有关联记录ID,去重避免自关联递归场景下重复创建 related_record_ids = current_record.related_records.values_list('id', flat=True).distinct() # 批量给关联记录创建文档关联,直接复用当前文件对象,不会重复存储物理文件 related_docs = [ RecordDocument(record_id=rid, file=current_doc.file) for rid in related_record_ids ] RecordDocument.objects.bulk_create(related_docs) return Response( RecordDocumentSerializer(current_doc).data, status=status.HTTP_201_CREATED )
实现说明
- 字段取值逻辑:序列化器调用
is_valid()校验通过后,所有合法字段都会存放在serializer.validated_data字典中,直接按key取值即可,不需要手动从request.data中解析。 - 存储优化:给关联记录创建文档时直接复用当前已保存的
current_doc.file对象,Django文件存储不会重复上传物理文件,仅会新增数据库记录关联同一个文件路径,不会产生冗余存储占用。 - 异常兼容:增加
current_record判空、关联ID去重逻辑,兼容record为空、多对多自关联递归的边界场景,避免重复创建文档、死循环问题。 - 性能优化:用
bulk_create批量插入关联文档数据,比循环单条调用save减少数据库交互次数,性能更高。
内容的提问来源于stack exchange,提问作者mikan
相关产品推荐
相关产品推荐

