如何为Django Serializer类设置懒引用解决循环依赖类未定义错误
问题原因
Python类定义是从上到下顺序执行的,你在定义QuestionAnsweringModelResultsSerializer时,它引用的FillInTheBlanksAnsweringModelResultsSerializer还没有完成定义,直接在类属性中引用未定义的类就会抛出未定义错误,本质和跨文件循环导入一致。
解决方案
推荐使用原生支持的动态字段注入方式,无需额外依赖,稳定性最高:
将互相引用的字段从类属性中移除,改为在序列化器的__init__方法中动态添加到字段列表中,此时两个序列化器类都已经完成定义,不会出现未定义问题,修改后的代码如下:
class QuestionAnsweringModelResultsSerializer(ModelSerializer): answers = AnswerAnsweringModelResultsSerializer(many=True) images = QuestionAnsweringModelImagesResultsSerializer(many=True) written_answer_marking_settings = QuestionMarkingSettingsSerializer() parent_question = QuestionResultsSerializer() procedural_answers = ProceduralAnswerAnsweringSerializer(many=True) class Meta: model = QuestionAnsweringModel fields = '__all__' def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 运行到此处时,下方的FillInTheBlanksAnsweringModelResultsSerializer已经定义完成 self.fields['fill_in_the_blanks_answers'] = FillInTheBlanksAnsweringModelResultsSerializer(many=True) class FillInTheBlanksAnsweringModelResultsSerializer(ModelSerializer): class Meta: model = FillInTheBlanksAnsweringModel fields = '__all__' def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 运行到此处时,上方的QuestionAnsweringModelResultsSerializer已经定义完成 self.fields['question'] = QuestionAnsweringModelResultsSerializer()
如果你不想修改__init__方法,也可以使用SerializerMethodField实现按需序列化,示例如下:
from rest_framework.fields import SerializerMethodField class QuestionAnsweringModelResultsSerializer(ModelSerializer): answers = AnswerAnsweringModelResultsSerializer(many=True) images = QuestionAnsweringModelImagesResultsSerializer(many=True) written_answer_marking_settings = QuestionMarkingSettingsSerializer() parent_question = QuestionResultsSerializer() procedural_answers = ProceduralAnswerAnsweringSerializer(many=True) fill_in_the_blanks_answers = SerializerMethodField() def get_fill_in_the_blanks_answers(self, obj): return FillInTheBlanksAnsweringModelResultsSerializer(obj.fill_in_the_blanks_answers.all(), many=True, context=self.context).data class Meta: model = QuestionAnsweringModel fields = '__all__' class FillInTheBlanksAnsweringModelResultsSerializer(ModelSerializer): question = SerializerMethodField() def get_question(self, obj): return QuestionAnsweringModelResultsSerializer(obj.question, context=self.context).data class Meta: model = FillInTheBlanksAnsweringModel fields = '__all__'
不过这种方法返回的是序列化后的字典,不是序列化器字段实例,部分DRF特性比如自动生成OpenAPI文档会受影响,因此更推荐第一种方法。
内容的提问来源于stack exchange,提问作者Freduah Gideon
相关产品推荐
相关产品推荐

