Django rest framework Django Rest框架不响应嵌套数据上的只读
我无法让DRF允许在一个序列化程序中提供嵌套数据的只读版本和列表中ID的可写版本。对我来说,这感觉像是一个bug,但通常这只是意味着我对框架的理解不够好,并且被错误消息误导了Django rest framework Django Rest框架不响应嵌套数据上的只读,django-rest-framework,Django Rest Framework,我无法让DRF允许在一个序列化程序中提供嵌套数据的只读版本和列表中ID的可写版本。对我来说,这感觉像是一个bug,但通常这只是意味着我对框架的理解不够好,并且被错误消息误导了 class Individual(models.Model): household = models.ForeignKey( 'household.Household', null=True, related_name="individuals") name = models.C
class Individual(models.Model):
household = models.ForeignKey(
'household.Household',
null=True,
related_name="individuals")
name = models.CharField(
max_length=100, default='')
class Household(models.Model):
address_line1 = models.CharField(max_length=64, default='')
class IndividualListSerializer(serializers.ModelSerializer):
class Meta:
model = Individual
depth = 0
fields = ('url', 'id', 'name', 'household')
read_only_fields = fields
class HouseholdUpdateSerializer(serializers.ModelSerializer):
individuals_details = IndividualListSerializer(many=True, source='individuals', read_only=True)
class Meta:
model = Household
fields = ('id', 'address_line1', 'individuals', 'individuals_details')
read_only_fields = ('id', 'individuals_details')
错误返回为
AssertionError: The `.update()` method does not support writable nested fields by default. Write an explicit `.update()` method for serializer `household.serializers.HouseholdUpdateSerializer`, or set `read_only=True` on nested serializer fields. // Werkzeug Debugger</title>
AssertionError:默认情况下,`.update()`方法不支持可写嵌套字段。为序列化程序`house.serializers.HouseholdUpdateSerializer`编写一个显式的`update()`方法,或在嵌套的序列化程序字段上设置`read\u only=True`。//Werkzeug调试器
我在嵌套字段上使用了read_(在响应更新时需要)。然而,这个错误仍然表明我没有这样做
如果我完全删除personals
字段,那么personals\u details
将返回可读数据,而不会出现错误,但因为它忽略了发送的personals
数据,所以不会更新该列表
如果我删除personals\u details
字段,DRF将接受personals
列表并对模型执行更新。但是,所需的返回数据并不存在
因此,当读嵌套列表或写列表各自工作时,当添加另一个时,序列化程序无法工作
这似乎是人们陷入困境的一个相当普遍的领域,而且答案似乎已经成为一种模式的最佳实践。但由于某些原因,它在我的代码中不起作用。也许是因为我的模型里有很多
我可能可以通过更改客户端来执行更新的PUT,忽略响应,然后执行单独的GET来解决这个问题,但是如果DRF更新可以按预期工作,那么这是草率的,不需要这样做
我在这方面遗漏了什么?您问了几个问题,因此我将从表示开始。实际上,对于完整的
单个
视图,您不需要单独的字段,您只需将转换为表示方法即可
class HouseholdUpdateSerializer(serializers.ModelSerializer):
class Meta:
model = Household
fields = ('id', 'address_line1', 'individuals')
def to_representation(self, instance):
representation = super(HouseholdUpdateSerializer, self).to_representation(instance)
representation['individuals'] = IndividualListSerializer(instance.individuals.all(), many=True).data
return representation
通常,当您需要更新模型的相关字段时,应该重写create
和update
序列化程序方法
class HouseholdUpdateSerializer(serializers.ModelSerializer):
....
def update(instance, validated_data):
# get and remove individuals from validated_data
individuals = validated_data.pop('individuals')
# delete all related links to individuals
# You could provide some validation before clear, check if provided pks exists in db table
instance.individuals.clear()
# update related links with new individuals
instance.individuals.add(*individuals)
# call super to provide update for other fields
return super(HouseholdUpdateSerializer, self).update(validated_data)
create
可能在您的情况下运行良好,而不需要重写。如果它不只是像update
那样编写,我不确定只读字段
是否适用于显式定义的字段。如何从只读字段中删除个人详细信息?它修复了吗?还要注意,这是一种反模式,在同一个模型中同时使用关系字段和嵌套序列化程序。我的目标不是同时使用关系字段和嵌套序列化程序。但是DRF不允许我只更新嵌套数据的ID。那么,在更改哪些ID相关之后,获取子记录详细信息的好模式是什么呢?覆盖to_表示满足了我的需要。我不清楚重写update方法的第二部分在做什么。我的猜测是,我还需要为个人定制验证器?@Shanemgree您可以在清除数据库中的链接之前检查个人
密钥是否存在。如果某个键出错,您将抛出异常,然后在视图层中使用If serializer.is\u valid():..
表达式或serializer.save(raise\u exception=True)
。您可以使用queryset.exists()
为每个密钥验证密钥,或者检查密钥的len
,并在数据库中对密钥进行计数,就像这样如果len(personals)=personals.objects.filter(pk\uu in=personals.count()
。