当前位置: 首页 > 面试题库 >

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

哈烨熠
2023-03-14
问题内容

使用 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,并为page给定的每个序列号book创建一个新页面或更新(如果存在)。

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默认情况下自动生成的一组字段,会更简单。



 类似资料:
  • 问题内容: 我正在编写一个食谱管理器作为课程的示例项目。除了使用一些非常基本的功能之外,我对DRF并没有太多的经验。目的是: 创建具有相关成分的新配方。在创建配方对象的同时创建成分对象。 models.py: serializers.py 这样可以在数据库中成功创建配方对象和配料对象,但不会将配料列表与配方相关联。我认为这是因为运行时字典中的成分被删除了,所以当我使用创建新的配方时,没有相关的成分

  • 问题内容: 我有一个带有自我参照字段的模型,称为parent。模型: 序列化器: 现在,我要序列化区域的父级及其父级及其父级,直到父级为none。我发现了针对孩子而不是父母的递归序列化方法。我怎样才能做到这一点? 问题答案: 尝试在此处使用SerializerMethodField: 我不确定DRF是否有内置方法,但是您可以使用查询来获取所需的方法。

  • 问题内容: 我使用的是Django Rest Framework,其中有以下两个序列化器: ServiceType模型如下所示: 我想通过更改相关服务(例如删除其中的一些服务)来更新现有实例。为此,我正在这样做: 我面临的问题是没有提供该字段-这意味着我得到了-尽管我在 字段中明确添加了该字段。 编辑 这是我发布的一个示例性请求(来自Chrome): 我在做什么错以及如何使用嵌套序列化程序获取对象

  • 问题内容: 在Django Rest Framework中,当一个序列化器嵌套在另一个序列化器中时,如何过滤它? 我的过滤器被强加在DRF视图集中,但是当您从另一个序列化器内部调用序列化器时,嵌套序列化器的视图集将永远不会被调用,因此嵌套结果看起来是未经过滤的。 我尝试在原始视图集上添加过滤器,但是它似乎无法过滤嵌套结果,因为嵌套结果被称为单独的预提取查询。(您看到嵌套的序列化程序是反向查找。)

  • 问题内容: 我曾经使用 allow_add_remove = True ,它在Django rest 2.0中可用,用于编写可嵌套的序列化程序,但在3.0中不可用,我很难实现它。 我想做这样的事情 现在我不知道如何在DRF 3.0中实现allow_add_remove行为 我很困惑,我需要重写UserSerializer和方法吗 或者我需要为每个模型创建单独的IdeaListSerializer

  • 考虑: 如果我们序列化Foo(),输出是: 我想要: 最干净的方法是什么?