无法理解django rest框架中列表序列化程序更新的流程

时间:2017-10-18 15:28:40

标签: python django django-rest-framework

我使用list Serializer by many = True。 create方法运行完美但我无法理解django rest框架文档中列表序列化程序的自定义更新方法的流程。使用列表序列化程序的基础是明确的,但是当我在代码中使用它时,流程是不可理解的。我无法理解第四行中book.items的含义。什么是书?在文档中,它还要求向实例序列化程序添加显式id字段。默认隐式生成的id字段标记为read_only。希望了解正在说什么文档以及如何实现它。文档的上下文如下所示。

class BookListSerializer(serializers.ListSerializer):
def update(self, instance, validated_data):
    # Maps for id->instance and id->data item.
    book_mapping = {book.id: book for book in instance}
    data_mapping = {item['id']: item for item in validated_data}

    # Perform creations and updates.
    ret = []
    for book_id, data in data_mapping.items():
        book = book_mapping.get(book_id, None)
        if book is None:
            ret.append(self.child.create(data))
        else:
            ret.append(self.child.update(book, data))

    # Perform deletions.
    for book_id, book in book_mapping.items():
        if book_id not in data_mapping:a
            book.delete()

    return ret

2 个答案:

答案 0 :(得分:0)

instance是一个书籍列表,即要序列化的类的对象。 validated_data是一个数据字典列表,其中每个item类似于您传递的validated_data,如果您使用的是非列表序列化程序。要访问图书对象的ID,您可以使用book.id来访问validated_data中商品的ID,您可以使用商品[' id']。 您需要一个非read_only id字段,因为如果您想要放置一个对象列表并替换整个集合,您需要传递ID以便定义一个项目是否应更新现有项目,如果是,则需要一个,或者如果一个项目是新的。这就是循环中发生的事情:在第一个循环中,项目要么被创建要么被更新,这取决于存在或不存在相同id的对象。在最后一个循环中,所有不在validated_data中显示的项目都会被删除。

答案 1 :(得分:0)

DRF 的文档有时有点过于“期望您了解 x 和 y 来自何处”,而不是提供更清晰的示例。这可能有助于将改进后的代码推送到您的代码库中,但是,改进后的代码在代码可读性方面并不总是更好(这也应该是开发人员技能的重要组成部分)。

无论如何,我遇到了与您提供的代码相同的问题,经过一些修补后,我想通了。

<块引用>
    # Maps for id->instance and id->data item.
    book_mapping = {book.id: book for book in instance}
    data_mapping = {item['id']: item for item in validated_data}

[x for x in y] 的模式被称为 list comprehension,它只是基于列表重新格式化列表或字典的一种线性方式。 由于在这些情况下,id 总是唯一的,因此可以预期生成的 dict 具有唯一的键,这些键将书或项目作为它们的值。

所以,即,如果实例是

instance = [
  {
    "id": 2,
    "title": "hobbit",
    "author": "Megan"
  },
  {
    "id": 3,
    "title": "Milk",
    "author": "Eric"
  },
  ...
]

那么书籍映射的结果将是

book_mapping = {book.id: book for book in instance}
book_mapping = {
  "2": {
    "id": 2,
    "title": "hobbit",
    "author": "Megan"
  },
  "3": {
    "id": 3,
    "title": "Milk",
    "author": "Eric"
  }
}