簡體   English   中英

django-rest-framework 3.0在嵌套序列化程序中創建或更新

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

就是這樣!

如果您不需要兩者,該庫也僅支持使用createupdate邏輯之一。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM