[英]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.