使用 django-rest-framework 3.0 并具有以下简单模型:
class Book(models.Model):
title = models.CharField(max_length=50)
class Page(models.Model):
book = models.ForeignKey(Books, related_name='related_book')
text = models.CharField(max_length=500)
并且给出了这个JSON请求:
{
"book_id":1,
"pages":[
{
"page_id":2,
"text":"loremipsum"
},
{
"page_id":4,
"text":"loremipsum"
}
]
}
如何编写嵌套的序列化程序来处理此JSON,并为给定 book
的每个 page
创建新页面或更新(如果存在) .
class RequestSerializer(serializers.Serializer):
book_id = serializers.IntegerField()
page = PageSerializer(many=True)
class PageSerializer(serializers.ModelSerializer):
class Meta:
model = Page
我知道使用 instance
实例化序列化程序会更新当前的序列化程序但是我应该如何在嵌套序列化程序的 create
方法中使用它?
2 回答
首先,您是要支持创建新书实例还是仅更新现有实例?
如果你只想创建新的书籍实例,你可以做这样的事情......
请注意,我没有在这里包含
book_id
. 当我们're creating book instances we won' t包括书籍ID . 当我们're updating book instances we'll通常将book id作为URL的一部分而不是在请求数据中 .如果要同时支持创建和更新工作簿实例,则需要考虑如何处理未包含在请求中但当前与工作实例关联的页面 .
您可以选择静默忽略这些页面并保持原样,您可能希望引发验证错误,或者您可能希望删除它们 .
假设您要删除请求中未包含的任何页面 .
您可能还希望仅支持书籍更新,而不支持创建,在这种情况下,只包括
update()
方法 .还有各种方法可以减少查询次数,例如 . 使用批量创建/删除,但上面会以相当简单的方式完成工作 .
正如您所看到的,在处理嵌套数据时您可能需要的行为类型存在微妙之处,因此请仔细考虑您在各种情况下期望的行为 .
另请注意,我在上面的示例中一直使用
Serializer
而不是ModelSerializer
. 在这种情况下,仅显式地包含序列化程序类中的所有字段更简单,而不是依赖于ModelSerializer
默认生成的自动字段集 .你可以简单地使用drf-writable-nested . 它会自动使嵌套的序列化程序可写和可更新 .
在你
serializers.py
:就是这样!
如果您不需要两者,库也支持仅使用
create
和update
逻辑中的一个 .