首先,你要支持创建新的图书实例还是仅更新现有图书实例?
如果你只想创建新的图书实例,则可以执行以下操作…
class PageSerializer(serializers.Serializer):
text = serializers.CharField(max_length=500)
class BookSerializer(serializers.Serializer):
page = PageSerializer(many=True)
title = serializers.CharField(max_length=50)
def create(self, validated_data):
# Create the book instance
book = Book.objects.create(title=validated_data['title'])
# Create or update each page instance
for item in validated_data['pages']:
page = Page(id=item['page_id'], text=item['text'], book=book)
page.save()
return book
请注意,我没有在book_id
此处添加。在创建图书实例时,我们不会包含图书ID。在更新图书实例时,通常会将图书ID包含在URL中,而不是包含在请求数据中。
如果你想支持创建和书籍实例的更新,那么你需要考虑一下你要如何处理未包含在请求页面,但在当前与书实例相关联。
你可能会选择静默忽略那些页面并保持原样,或者想要引发验证错误,或者想要删除它们。
def create(self, validated_data):
# As before.
...
def update(self, instance, validated_data):
# Update the book instance
instance.title = validated_data['title']
instance.save()
# Delete any pages not included in the request
page_ids = [item['page_id'] for item in validated_data['pages']]
for page in instance.books:
if page.id not in page_ids:
page.delete()
# Create or update page instances that are in the request
for item in validated_data['pages']:
page = Page(id=item['page_id'], text=item['text'], book=instance)
page.save()
return instance
你也可能只希望支持书籍更新,而不希望支持创建,在这种情况下,仅包含update()
方法。
你还可以通过多种方式减少查询数量,例如。使用批量创建/删除操作,但以上操作将以非常简单的方式完成工作。
如你所见,在处理嵌套数据时,你可能想要的行为类型有些微妙,因此请仔细考虑在各种情况下期望的行为。
另请注意,我Serializer
在上面的示例中一直使用而不是ModelSerializer
。在这种情况下,仅将所有字段显式包括在serializer
类中,而不是依靠ModelSerializer
默认情况下自动生成的字段集,会更简单。