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,对于给定的书
,每个页面
可以创建一个新页面或更新(如果存在)
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
我知道用实例
实例化序列化程序将会更新当前一个,但是如何在嵌套的串行器的创建
方法中使用它?
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作为网址的一部分,而不是请求数据。
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()
方法。
还有各种方法可以减少查询的数量,例如。使用批量创建/删除,但上述将以一种相当简单的方式来完成这项工作。
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屋!