instance.save()未在ListSerializer Django Rest框架中保存模型

instance.save()未在ListSerializer Django Rest框架中保存模型,django,django-rest-framework,Django,Django Rest Framework,在Django Rest Framework ListSerializer中,当我想通过调用instance.save()将验证过的数据保存到数据库时,我得到一个错误,说queryset对象没有属性save ListSerializer类: class NoAccessDetailsListSerializer(serializers.ListSerializer): # This will be called when there is list of objects #he

在Django Rest Framework ListSerializer中,当我想通过调用instance.save()将验证过的数据保存到数据库时,我得到一个错误,说queryset对象没有属性save

ListSerializer类:

class NoAccessDetailsListSerializer(serializers.ListSerializer):

    # This will be called when there is list of objects
    #here instance is list of queryset and validated_data is the list of json object
    def update(self, instance, validated_data):

        ret = []
        for index, data in enumerate(validated_data):

            #checking if row is already chosen
            if(instance[index].row_chosen):

                # do not update the info to db
                # just append the data to ret
                ret.append(instance[index])

            else:
                instance.id = instance[index].id
                instance.row_chosen = validated_data[index].get(
                    'row_chosen')
                instance.user_working = validated_data[index].get(
                    'user_working')

                ret.append(instance)

                instance.save()

        return ret
序列化程序类

class NoAccessDetailsSerializer(serializers.ModelSerializer):


    id = serializers.IntegerField(read_only=False)

    class Meta:
        model = NoAccessDetails
        list_serializer_class = NoAccessDetailsListSerializer
        fields = ("id", "row_chosen",
                  "user_working")

    def update(self, instance, validated_data):
        instance.id = instance.id
        instance.row_chosen = validated_data.get(
            'row_chosen')
        instance.user_working = validated_data.get(
            'user_working ')

        instance.save()
        return instance
基本上,在ListSerializer中,我正在检查数据库中是否已经选择了该行。如果为True,那么我只是将实例数据附加到字典中,否则我想将数据更新到数据库中,并将更新后的数据附加到列表中并返回它

在ListSerializer中,我将从APIView类中传递过滤后的queryset作为实例,validated_数据是一个已验证数据的列表

我将传递给APIView类的示例JSON数据:

[
        {
            "id": 1,
            "row_chosen": true,
            "user_working": "John"
        },
        {
            "id": 1,
            "row_chosen": true,
            "user_working": "David"
        },
]
当我传递JSON数据时,它将正确地从DB中过滤出行,并将queryset作为实例和JSON数据传递给serializer类

# here list_of_id is the ids which are there in the JSON object. i.e [1,2]

filtered_id_data= NoAccessDetails.objects.filter(
                id__in=list_of_id)

            serializer = NoAccessDetailsSerializer(filtered_id_data,
                                                   data=request.data,
                                                   many=True,
                                                   )

ListSerializer update()正在工作,但当它运行else块并尝试更新数据时,会出现错误queryset对象没有属性save。而在序列化程序的update()中,它运行instance.save()并更新单个对象的数据。我不确定我在哪里犯了错误。 请帮我做这个

更新:

class NoAccessDetails(models.Model):
    20 CharFields
    ...
    ...
    user_working = models.ForeignKey(
        UserProfile, on_delete=models.CASCADE, blank=True, null=True)
    row_chosen = models.BooleanField(default=False)

class UserProfile(models.Model):
    user_id = models.CharField(primary_key=True, max_length=10)
    user_name = models.CharField(max_length=100)
    user_email = models.EmailField()
    is_admin = models.BooleanField(default=False)

我将ListSerializer类中的instance.save()更改为instance[index].save()。现在,queryset对象没有属性save已修复。即使在使用实例[index].save()时,我也无法将数据保存在数据库中

型号:

class NoAccessDetails(models.Model):
    20 CharFields
    ...
    ...
    user_working = models.ForeignKey(
        UserProfile, on_delete=models.CASCADE, blank=True, null=True)
    row_chosen = models.BooleanField(default=False)

class UserProfile(models.Model):
    user_id = models.CharField(primary_key=True, max_length=10)
    user_name = models.CharField(max_length=100)
    user_email = models.EmailField()
    is_admin = models.BooleanField(default=False)

在NoAccessDetail模型中,我将user_保持为null true,因为此模型的数据将来自不同的源。最初在导入数据时,用户_工作将为空。更新API调用中的数据时,我正在验证JSON数据。

要调用.save()方法,必须在模型实例上调用它,而不是在模型的查询集上调用它。根据DRF文件

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:
            book.delete()

    return ret
您可以看到他们正在使用book_映射。这是创建一个字典,其中键是书的id,值是书的实例

希望这有帮助

编辑 检查“else:”块下方的行。您会发现需要使用.get()获取要更新的模型的对象,然后使用.save()方法

重新编辑 使用实例[index].save()也可以。我认为在附加到ret之前需要调用obj.save()

class NoAccessDetailsListSerializer(serializers.ListSerializer):
    def update(self, instance, validated_data):
        ...
        ...
        else:
            obj = NoAccessDetails.objects.get(id=instance[index].id)
            # or obj = instance[index]
            obj.row_chosen = validated_data[index].get(
                'row_chosen')
            obj.user_working = validated_data[index].get(
                'user_working')

            print('Instance data ',
                  obj.row_chosen,
                  obj.user_working)
            obj.save() # call this before appending to ret
            ret.append(obj)


    return ret
重新编辑

我根据文档更新了代码片段

class NoAccessDetailsListSerializer(serializers.ListSerializer):

# This will be called when there is list of objects
# here instance is list of queryset and validated_data is the list of json object
def update(self, instance, validated_data):

    ret = []

    obj_mapping = {obj.id: obj for obj in instance}
    data_mapping = {item['id']: item for item in validated_data}

    for obj_id, data in data_mapping.items():
        obj = obj_mapping.get(obj_id, None)
        if not obj:
            continue

        if obj.row_chosen:
            ret.append(obj)
        else:
            obj.row_chosen = data['row_chosen']
            obj.user_working = data['user_working']
            obj.save()
            ret.append(obj)

    return ret

它是一个ListSerializer,因此这里的实例是一个列表,即queryset,而不是一个实例或对象。是的,它是queryset的列表@Mehran我哪里都错了,你能纠正我吗?基本上,你需要循环遍历实例(因为它是一个列表),并对每个项调用.save()。我已经发布了一个答案,引用了docsI尝试过的实例[index].save()中的代码,但这次它不会给我任何错误,而是不会将对象保存在数据库中。在我的代码中,我像NoAccessDetailsSerializer这样做(过滤的\u id\u数据,数据=request.data,多个=True)其中过滤的\u id\u数据是查询集。而不是传递我需要传递的查询集?当然!让我知道它是否有效!我个人从来没有真正费心使用ListSerializer,总是坚持使用ModelSerializer或basic Serializer(如果没有连接任何模型)并且想知道您是否有一个需要更新的对象列表,您会怎么做?在文档本身中,他们提到要使用ListSerializer.hey@Mehran,上面的代码实际上是有效的。但是,实例[index].save()并没有将数据保存在数据库中。而在update()中在ModelSerializer中,通过调用instance.save()保存数据。你有什么想法吗?嘿@Mehran!我真的不知道,它突然开始工作正常。现在正在工作的用户和所选行的数据都保存在数据库中。谢谢你,我的朋友。非常感谢你在整个问题中帮助我。谢谢:)