django-rest-framework 3.0在嵌套序列化程序中创建或更新 [英] django-rest-framework 3.0 create or update in nested serializer

查看:144
本文介绍了django-rest-framework 3.0在嵌套序列化程序中创建或更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆