instance.save()未在ListSerializer Django Rest框架中保存模型
在Django Rest Framework ListSerializer中,当我想通过调用instance.save()将验证过的数据保存到数据库时,我得到一个错误,说queryset对象没有属性save ListSerializer类: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
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!我真的不知道,它突然开始工作正常。现在正在工作的用户和所选行的数据都保存在数据库中。谢谢你,我的朋友。非常感谢你在整个问题中帮助我。谢谢:)