Django DRF如何实现Survey/Question/Option嵌套模型的POST批量保存
嵌套数据一次性提交实现方案
不需要为每个模型单独创建接口,只需要重写序列化器的create方法处理嵌套关联逻辑,再调整视图支持POST请求即可,具体实现如下:
1. 重写Survey序列化器的create方法
DRF默认不支持嵌套结构的写入操作,需要手动实现层级创建逻辑,同时加事务保证数据一致性:
from django.db import transaction from rest_framework import serializers # 原有OptionSerializer、QuestionSerializer不需要修改 class OptionSerializer(serializers.ModelSerializer): class Meta: model = Option exclude = ('question','id') class QuestionSerializer(serializers.ModelSerializer): options = OptionSerializer(many=True) class Meta: model = Question exclude = ('survey',) class SurveyDetailSerializer(serializers.ModelSerializer): creator = serializers.StringRelatedField(read_only=True) questions = QuestionSerializer(many=True) class Meta: model = Survey exclude = ('is_active',) @transaction.atomic def create(self, validated_data): # 提取关联的问题数据 questions_data = validated_data.pop('questions') # 先创建问卷主表,creator为只读字段,从请求上下文取当前登录用户 survey = Survey.objects.create( creator=self.context['request'].user, **validated_data ) # 遍历创建所有问题 for question_data in questions_data: options_data = question_data.pop('options') # 创建问题并关联当前问卷 question = Question.objects.create(survey=survey, **question_data) # 遍历创建当前问题的所有选项 for option_data in options_data: Option.objects.create(question=question, **option_data) return survey
2. 调整视图支持POST请求
原有视图仅支持GET查询,调整后同时支持查询和创建:
from rest_framework import generics, mixins class SurveyView(mixins.RetrieveModelMixin, mixins.CreateModelMixin, generics.GenericAPIView): """查询单份问卷、创建完整问卷接口""" queryset = Survey.objects.all() serializer_class = SurveyDetailSerializer # 处理GET查询请求 def get(self, request, *args, **kwargs): return self.retrieve(request, *args, **kwargs) # 处理POST创建请求 def post(self, request, *args, **kwargs): return self.create(request, *args, **kwargs)
如果不需要同一路径支持查询,也可以单独使用generics.CreateAPIView实现创建接口。
3. 前端提交格式
和GET返回格式基本一致,只需要剔除只读字段(id、creator、created_at等)即可,提交示例:
{ "name": "新调查问卷", "description": "问卷描述内容", "questions": [ { "answer_type": "single option", "text": "第一题内容?", "options": [ {"text": "选项A"}, {"text": "选项B"} ] } ] }
补充说明
- 如果后续需要支持嵌套更新(PUT/PATCH),同理重写序列化器的
update方法即可,逻辑为:先更新问卷主字段,再对比处理关联的问题、选项的新增/修改/删除操作。 - 原有字段校验逻辑会自动生效,不需要额外修改。
内容的提问来源于stack exchange,提问作者Alice_nvbr
相关产品推荐
相关产品推荐

