[英]django-rest-framework 3.0 create or update in nested serializer
使用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
方法中使用它呢?
首先,您要支持创建新的图书实例还是仅更新现有图书实例?
如果您只想创建新的图书实例,则可以执行以下操作...
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
生成的自动字段集,会更ModelSerializer
。
您可以简单地使用drf-writable-nested 。 它会自动使您的嵌套序列化器可写和可更新。
在您serializers.py
:
from drf_writable_nested import WritableNestedModelSerializer
class RequestSerializer(WritableNestedModelSerializer):
book_id = serializers.IntegerField()
page = PageSerializer(many=True)
class PageSerializer(serializers.ModelSerializer):
class Meta:
model = Page
就是这样!
如果您不需要两者,该库也仅支持使用create
和update
逻辑之一。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.