Django Rest框架没有响应read_only对嵌套数据 [英] Django Rest Framework not responding to read_only on nested data

查看:225
本文介绍了Django Rest框架没有响应read_only对嵌套数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不能让DRF允许在一个串行器中的列表中提供一个只读的嵌套数据版本和一个可写版本的只是ids。对我来说感觉就像是一个错误,但通常这只是意味着我不足够理解框架,并被错误信息误导。

 code> class Individual(models.Model):
household = models.ForeignKey(
'household.Household',
null = True,
related_name =individual )
name = models.CharField(
max_length = 100,default ='')

class家庭(models.Model):
address_line1 = models.CharField max_length = 64,default ='')

class IndividualListSerializer(serializers.ModelSerializer):
class Meta:
model = Individual
depth = 0
field =('url','id','name','household')
read_only_fields = fields

class HouseholdUpdateSerializer(serializers.ModelSerializer):
persons_details = IndividualListSerializer many = True,source ='individual',read_only = True)
class Meta:
model = Household
fields =('id','address_line1','individual','personal_details')
read_only_fields =('id','personal_details')

错误返回为

  AssertionError :`.update()`方法默认不支持可写嵌套字段。为serializer`home.serializers.HouseholdUpdateSerializer`编写一个明确的`.update()`方法,或在嵌套的序列化程序字段上设置`read_only = True'。 // Werkzeug Debugger< / title> 

我在嵌套字段中使用了read_only(这在更新的响应中是必需的)。但是,错误仍然表明我没有这样做。



如果我完全删除个人字段, personal_details 返回可读数据而不会出错,但是由于它忽略了个人数据正在发送,所以不会更新该列表。



如果我删除 personal_details 字段,DRF接受个人列表并对模型执行更新。但是所需的返回数据不在那里。



所以,虽然读取嵌套或写入列表自己工作,但是当添加其他列表时,串行器不起作用。



这似乎是一个很常见的区域,人们陷入困境,似乎这个SO问题的答案已经成为模式的最佳实践。但是,由于某些原因它在我的代码中不起作用。也许是因为我的模型中的ManyToOne。



我可以通过更改客户端来执行更新的PUT来解决这个问题,忽略响应,然后单独执行GET,但是这是一个很大的问题,如果DRF更新可以按预期的方式工作,那么就不用了。



我在这里缺少什么?

解决方案

你问几个问题,所以我先从代表开始。实际上,您不需要单独的字段来满足个人视图,您可以只是ovveride to_representation 方法。

  class HouseholdUpdateSerializer(serializers.ModelSerializer):

class Meta:
model =
fields =('id','address_line1','individual')

def to_representation(self,instance):
representation = super(HouseholdUpdateSerializer,self).to_representation实例)
表示['individual'] = IndividualListSerializer(instance.individuals.all(),many = True).data
返回表示
创建和 update serializer方法。

  class HouseholdUpdateSerializer(serializers.ModelSerializer):
....
def update(instance,validated_data )
#从validated_data获取和删除个人
个人= validated_data.pop('个人')
#删除所有相关链接到个人
#您可以在清除之前提供一些验证,检查db表中是否存在pks
instance.individuals.clear()
#更新与新个人相关的链接
instance.individuals.add(*个人)
#call超级为其他字段提供更新
返回超级(HouseholdUpdateSerializer,self).update(validated_data)

创建可能会在您的情况下运行良好而不会覆盖。如果它不只是写得类似于 update


I can't get DRF to allow providing a read_only version of nested data and a writeable version of just the ids in a list in one serializer. It feels like a bug to me, but usually that just means I'm not understanding the framework well enough, and being misled by the error message.

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

The error comes back as

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>

I have used read_only on the nested field (which is needed in the response to the update). Yet the error still indicates I am not doing so.

If I remove the individuals field entirely, the individuals_details returns the readable data without the error, but since it's ignoring the individuals data being sent, it isn't updating that list.

If I remove the individuals_details field, DRF accepts the individuals list and performs the update on the model. But then the return data needed is not there.

So, while either the read nested or write list work on their own, when the other is added the serializer doesn't function.

This seems a pretty common area people get stuck, and it seems the answers this SO question have become the best practice for a pattern. But it doesn't work in my code for some reason. Perhaps because of the ManyToOne in my models.

I can probably work around this by changing the client to perform the PUT for the update, ignore the response, and then do a separate GET, but that's sloppy and shouldn't be needed if the DRF update can be made to work as expected.

What am I missing in this?

解决方案

You ask several questions so I'll start with the representation. Actually you don't need separate field for full Individual view you could just ovveride to_representation method.

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

Usually when you want update related fields of your model you should override create and update serializer methods.

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 will probably works well in your case without overriding. If it not just write it similar to update.

这篇关于Django Rest框架没有响应read_only对嵌套数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆