Django rest framework Django Rest框架不响应嵌套数据上的只读

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

我无法让DRF允许在一个序列化程序中提供嵌套数据的只读版本和列表中ID的可写版本。对我来说,这感觉像是一个bug,但通常这只是意味着我对框架的理解不够好,并且被错误消息误导了

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()