Python Django rest_framework 3.22多次更新创建对象而不是更新
我有一个API,它需要以列表的形式返回QuestionQueue及其关联的问题对象。我让它工作得很好,它以我想要的方式返回数据:Python Django rest_framework 3.22多次更新创建对象而不是更新,python,django,rest,django-rest-framework,Python,Django,Rest,Django Rest Framework,我有一个API,它需要以列表的形式返回QuestionQueue及其关联的问题对象。我让它工作得很好,它以我想要的方式返回数据: class QuestionQueueSerializer(serializers.ModelSerializer): questions = QuestionSerializer( many=True, source='question_set', required=False, ) 我在获取此API
class QuestionQueueSerializer(serializers.ModelSerializer):
questions = QuestionSerializer(
many=True,
source='question_set',
required=False,
)
我在获取此API的更新时遇到问题。我正在遵循多次写入的规则。我有自己的自定义ListSerializer
实例,名为QuestionListSerializer
。下面是我如何在QuestionQueueSerializer
中使用它:
def update(self, instance, validated_data):
questions_data = validated_data.pop('question_set')
super(QuestionQueueSerializer, self).update(instance, validated_data)
question_list_serializer = QuestionSerializer(
instance=instance.question_set.all(),
data=questions_data,
many=True
)
if question_list_serializer.is_valid():
question_list_serializer.save(
company_id=instance.company_id,
question_queue_id=instance.id
)
return instance
以下是QuestionListSerializer
上的更新方法,我已将其设置为我的QuestionSerializer
上的list\u serializer\u类
:
def update(self, instance, validated_data):
questions_by_id = {_question.id: _question for _question in instance}
# Perform creations and updates.
ret = []
for question_data in validated_data:
question = None
if 'id' in question_data:
question = questions_by_id.get(question_data['id'], None)
if not question:
ret.append(self.child.create(question_data))
else:
ret.append(self.child.update(question, question_data))
question_ids_to_delete = set(questions_by_id.keys()) - {_q.id for _q in ret}
Question.objects.filter(id__in=question_ids_to_delete).update(delete_ts=timezone.now())
return ret
问题是,当调用我的
QuestionListSerializer
的update
方法时,validated\u数据
不包含问题的ID。它们看起来都是新创建的。request.data
中的问题都有ID。他们在路上的某个地方脱光了衣服。我不知道如何让它工作。问题是,id
字段在DRF的ModelSerializer
中是read\u=True
,因此它们在验证周期中被丢弃。使更新生效需要更多的工作。我不得不做一些类似的事情,最终得到的解决方案是创建一个序列化程序mixin,将id放回原处。您可以看到源代码。此外,我还有一些额外的信息在报告中
如果代码被移动或类似情况,下面是序列化程序mixin的复制粘贴:
class BulkSerializerMixin(object):
def to_internal_value(self, data):
ret = super(BulkSerializerMixin, self).to_internal_value(data)
id_attr = getattr(self.Meta, 'update_lookup_field', 'id')
request_method = getattr(getattr(self.context.get('view'), 'request'), 'method', '')
# add update_lookup_field field back to validated data
# since super by default strips out read-only fields
# hence id will no longer be present in validated_data
if all((isinstance(self.root, BulkListSerializer),
id_attr,
request_method in ('PUT', 'PATCH'))):
id_field = self.fields[id_attr]
id_value = id_field.get_value(data)
ret[id_attr] = id_value
return ret
我在IRC上和汤姆克里斯蒂谈过。在我的序列化程序中添加一个显式id字段并使其不可读只解决了这个问题。我尝试将此代码复制到我的代码库中,但无法使其工作。我左顾右盼都没有用。在某些对内部值的调用中,`context`不包含
视图
。如果根目录是我的列表的一个实例,则它不包含字段
。我准备完全放弃rest_框架,因为要让它做我需要的事情非常困难。如果root是一个列表,它将不包含任何字段<代码>根.child.field将存在<代码>列表序列化程序不包含任何字段。所有字段都回退到子序列化程序字段。