django-rest-framework 3.0 在嵌套序列化程序中创建或更新 [英] django-rest-framework 3.0 create or update in nested serializer
问题描述
使用 django-rest-framework 3.0 并拥有这些简单的模型:
With django-rest-framework 3.0 and having these simple models:
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 请求:
And given this JSON request:
{
"book_id":1,
"pages":[
{
"page_id":2,
"text":"loremipsum"
},
{
"page_id":4,
"text":"loremipsum"
}
]
}
如何编写嵌套序列化程序来处理此 JSON,并为给定 book
的每个 page
创建一个新页面或更新(如果存在).
How can I write a nested serializer to process this JSON and for each page
for the given book
either create a new page or update if it exists.
class RequestSerializer(serializers.Serializer):
book_id = serializers.IntegerField()
page = PageSerializer(many=True)
class PageSerializer(serializers.ModelSerializer):
class Meta:
model = Page
我知道用 instance
实例化序列化器会更新当前的序列化器,但是我应该如何在嵌套序列化器的 create
方法中使用它?
I know that instantiating the serializer with an instance
will update the current one but how should I use it inside the create
method of nested serializer?
推荐答案
首先,您是要支持创建新的图书实例,还是仅更新现有的图书实例?
Firstly, do you want to support creating new book instances, or only updating existing ones?
如果您只想创建新书实例,您可以执行以下操作...
If you only ever wanted to create new book instances you could do something like this...
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 的一部分,而不是包含在请求数据中.
Note that I haven't included the book_id
here. When we're creating book instances we won't be including a book id. When we're updating book instances we'll typically include the book id as part of the URL, rather than in the request data.
如果您想同时支持图书实例的创建和更新,那么您需要考虑如何处理未包含在请求中但当前与图书实例相关联的页面.
If you want to support both create and update of book instances then you need to think about how you want to handle pages that are not included in the request, but are currently associated with the book instance.
您可能会选择默默地忽略这些页面并保持原样,您可能想要引发验证错误,或者您可能想要删除它们.
You might choose to silently ignore those pages and leave them as they are, you might want to raise a validation error, or you might want to delete them.
假设您要删除请求中未包含的所有页面.
Let's assume that you want to delete any pages not included in the request.
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()代码>方法.
It's also possible that you might want to only support book updates, and not support creation, in which case, only include the update()
method.
还有多种方法可以减少查询次数,例如.使用批量创建/删除,但上面的方法会以相当简单的方式完成这项工作.
There are also various ways you could reduce the number of queries eg. using bulk create/deletion, but the above would do the job in a fairly straightforward way.
正如您所见,在处理嵌套数据时您可能需要的行为类型存在细微差别,因此请仔细考虑您在各种情况下期望的行为.
As you can see there are subtleties in the types of behavior you might want when dealing with nested data, so think carefully about exactly what behavior you're expecting in various cases.
另请注意,我在上面的示例中一直使用 Serializer
而不是 ModelSerializer
.在这种情况下,只需显式包含序列化器类中的所有字段,而不是依赖 ModelSerializer
默认生成的自动字段集,就更简单了.
Also note that I've been using Serializer
in the above example rather than ModelSerializer
. In this case it's simpler just to include all the fields in the serializer class explicitly, rather than relying on the automatic set of fields that ModelSerializer
generates by default.
这篇关于django-rest-framework 3.0 在嵌套序列化程序中创建或更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!