我无法让DRF允许在一个序列化程序中提供嵌套数据的read_only版本和仅列表中的id的可写版本。这对我来说感觉像是一个错误,但通常这意味着我不能很好地理解框架,并被错误信息误导。
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>
我在嵌套字段上使用了read_only(在更新响应中需要)。但错误仍然表明我没有这样做。
如果我完全删除individuals
字段,individuals_details
会返回没有错误的可读数据,但由于它忽略了正在发送的individuals
数据,因此它不会更新该列表。
如果我删除individuals_details
字段,DRF会接受individuals
列表并对模型执行更新。但是那时所需的返回数据不存在。
因此,虽然读取嵌套或写入列表可以自行工作,但是当添加另一个时,序列化器不起作用。
这似乎是人们陷入困境的一个相当普遍的领域,似乎答案this SO question已成为模式的最佳实践。但由于某种原因,它在我的代码中不起作用。也许是因为我的模型中的ManyToOne。
我可以解决这个问题,方法是更改客户端以执行更新的PUT,忽略响应,然后执行单独的GET,但这很草率,如果可以使DRF更新工作则不需要如预期的那样。
我在这里错过了什么?
答案 0 :(得分:1)
你问几个问题所以我将从表示开始。实际上,对于完整Individual
视图,您不需要单独的字段,您可以只使用to_representation
方法。
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
。