我在为以下模型创建(嵌套)序列化程序时遇到问题:
class Chapter(Model):
uuid = UUIDField(primary_key=True, editable=False)
description = TextField(blank=True)
class Section(Model):
uuid = UUIDField(primary_key=True, editable=False)
description = TextField(blank=True)
chapter = ForeignKey(Chapter, related_name='sections', on_delete=CASCADE)
以下是使用create方法的章节模型的序列化程序:
class ChapterSerializer(ModelSerializer):
uuid = UUIDField(read_only=False)
sections = SectionSerializer(many=True, read_only=False)
class Meta:
model = Chapter
fields = ('uuid', 'description', 'sections')
def create(self, validated_data):
sections = validated_data.pop('sections', [])
chapter = Chapter.objects.create(**validated_data)
for section in sections:
section.update({'chapter': chapter})
section = Section.objects.create(**section)
return chapter
以下是Section序列化程序的两个略有不同的变体:
class SectionSerializer(ModelSerializer):
uuid = UUIDField(read_only=False)
chapter = PrimaryKeyRelatedField(read_only=true)
class Meta:
model = Section
fields = ('uuid', 'description', 'chapter')
class SectionSerializer(ModelSerializer):
uuid = UUIDField(read_only=False)
chapter = PrimaryKeyRelatedField(queryset=Chapter.objects.all())
class Meta:
model = Section
fields = ('uuid', 'description', 'chapter')
现在,如果我尝试创建一个带有嵌套Sections的新章节,并且Section序列化程序中的PrimaryKeyRelatedField
设置了queryset
参数,我会收到以下错误:
'sections': [{'chapter': ['Invalid pk "x" - object does not exist.']}]
如果我将变量与read_only=true
参数一起使用,则创建一个带有嵌套Sections的新章节,但现在我不能再创建一个新的Section(章节字段设置为现有章节UUID),因为章节验证输入数据时删除字段。
django.db.utils.IntegrityError: null value in column "chapter_id" violates not-null constraint
我想我可以通过复制SectionSerializer
来解决这个问题,但这似乎是一个非常粗糙的解决方案......
有人知道更好的方法吗?
答案 0 :(得分:1)
好的,回答我自己的问题:
我终于找到了一种方法来获得一个可嵌套的"和#34;可写"没有代码重复的SectionSerializer
的版本:
class NestedSectionSerializer(ModelSerializer):
uuid = UUIDField(read_only=False)
class Meta:
model = Section
exclude = ('chapter', )
class SectionSerializer(NestedSectionSerializer):
url = serializers.HyperlinkedIdentityField(view_name='section-detail')
class Meta:
model = Section
fields = '__all__'
class ChapterSerializer(ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='chapter-detail')
uuid = UUIDField(read_only=False)
sections = NestedSectionSerializer(many=True, read_only=False)
class Meta:
model = Chapter
fields = '__all__'
def create(self, validated_data):
sections = validated_data.pop('sections', [])
chapter = Chapter.objects.create(**validated_data)
for section in sections:
section.update({'chapter': chapter})
section = Section.objects.create(**section)
return chapter
这里的关键是明确排除对#34;嵌套"中的chapter
的崇敬。序列化程序,但在"可写"中再次添加它串行器。这甚至可以扩展到深层嵌套的结构!
通过使用继承,我可以避免大多数代码重复。
答案 1 :(得分:0)
我只是拉着我的头发讲述同样的问题。
答案实际上在DRF文档中:如果您希望它们可写,则需要明确定义PrimaryKeyRelatedField
的queryset参数。
在您的情况下,只需要SectionSerializer
的第二个变体。