DRF中如何序列化含多类型问题的Test模型?已编写各问题序列化器
解决方案
模型无需重构,可先做小优化
你的模型设计(用多表继承区分问题类型)是可行的,不需要重构,但可以加个小优化避免类型不匹配:给每个问题子类重写save方法,自动设置对应的type字段,确保数据一致性:
class TextQuestion(Question): answer = models.CharField(max_length=255) # 原代码未指定max_length,Django会报错,需补上 def save(self, *args, **kwargs): self.type = Question.Type.TEXT super().save(*args, **kwargs) class RadioQuestion(Question): variants = fields.ArrayField(models.CharField(max_length=255)) answer = models.CharField(max_length=255) def save(self, *args, **kwargs): self.type = Question.Type.RADIO super().save(*args, **kwargs) class ChoiceQuestion(Question): variants = fields.ArrayField(models.CharField(max_length=255)) answers = fields.ArrayField(models.CharField(max_length=255)) def save(self, *args, **kwargs): self.type = Question.Type.CHOICE super().save(*args, **kwargs)
用SerializerMethodField处理多类型问题序列化
你担心SerializerMethodField不能配合many=True是误解,完全可以实现。只需在TestSerializer中定义该字段,然后在对应的方法里遍历每个问题,根据类型选择序列化器即可:
from rest_framework import serializers from .models import Test from .serializers import TextQuestionSerializer, RadioQuestionSerializer, ChoiceQuestionSerializer class TestSerializer(serializers.ModelSerializer): questions = serializers.SerializerMethodField() class Meta: model = Test fields = ['name', 'creator', 'questions'] def get_questions(self, obj): serialized_list = [] # 遍历关联的所有Question实例 for question in obj.questions.all(): # 根据type字段匹配对应的子类序列化器 if question.type == question.Type.TEXT: # 多表继承下,通过子类小写名称的属性获取子类实例 serializer = TextQuestionSerializer(question.textquestion) elif question.type == question.Type.RADIO: serializer = RadioQuestionSerializer(question.radioquestion) elif question.type == question.Type.CHOICE: serializer = ChoiceQuestionSerializer(question.choicequestion) else: continue # 可根据需求处理未知类型 serialized_list.append(serializer.data) return serialized_list
可选:用第三方库简化多态序列化
如果觉得手动判断麻烦,可以用django-rest-polymorphic库,它专门处理DRF中的多态模型序列化。安装后只需定义一个多态序列化器,关联各个子类的序列化器,就能自动匹配:
from rest_polymorphic.serializers import PolymorphicSerializer class QuestionPolymorphicSerializer(PolymorphicSerializer): model_serializer_mapping = { TextQuestion: TextQuestionSerializer, RadioQuestion: RadioQuestionSerializer, ChoiceQuestion: ChoiceQuestionSerializer, } # 然后在TestSerializer中直接使用 class TestSerializer(serializers.ModelSerializer): questions = QuestionPolymorphicSerializer(many=True) class Meta: model = Test fields = ['name', 'creator', 'questions']
内容的提问来源于stack exchange,提问作者Gosha
相关产品推荐
相关产品推荐

