使用 Django REST 框架,标准 ModelSerializer 将允许通过将 ID 作为整数发布来分配或更改 ForeignKey 模型关系。
从嵌套序列化程序中获得这种行为的最简单方法是什么?
注意,我只是在谈论分配现有的数据库对象,不是嵌套创建。
我过去在序列化程序中使用额外的“id”字段以及自定义 create
和 update
方法解决了这个问题,但这看起来很简单我很想知道最好的方法。
class Child(models.Model):
name = CharField(max_length=20)
class Parent(models.Model):
name = CharField(max_length=20)
phone_number = models.ForeignKey(PhoneNumber)
child = models.ForeignKey(Child)
class ChildSerializer(ModelSerializer):
class Meta:
model = Child
class ParentSerializer(ModelSerializer):
# phone_number relation is automatic and will accept ID integers
children = ChildSerializer() # this one will not
class Meta:
model = Parent
最佳答案
2020 年 7 月 5 日更新
这篇文章越来越受到关注,这表明更多人有类似的情况。所以我决定添加一个通用方式来处理这个问题。如果您有更多需要更改为这种格式的序列化程序,这种通用方式最适合您
由于 DRF 没有提供开箱即用的功能,我们需要先创建一个序列化器字段。
from rest_framework import serializers
class RelatedFieldAlternative(serializers.PrimaryKeyRelatedField):
def __init__(self, **kwargs):
self.serializer = kwargs.pop('serializer', None)
if self.serializer is not None and not issubclass(self.serializer, serializers.Serializer):
raise TypeError('"serializer" is not a valid serializer class')
super().__init__(**kwargs)
def use_pk_only_optimization(self):
return False if self.serializer else True
def to_representation(self, instance):
if self.serializer:
return self.serializer(instance, context=self.context).data
return super().to_representation(instance)
这个类名RelatedFieldAlternative
给我留下了深刻的印象,你可以使用任何你想要的东西。
然后在您的父序列化程序中使用这个新的序列化程序字段,
class ParentSerializer(ModelSerializer):
<b>child = RelatedFieldAlternative(queryset=Child.objects.all(), serializer=ChildSerializer)</b>
class Meta:
model = Parent
fields = '__all__'
原帖
使用两个不同的字段会ok(如 @Kevin Brown 和 @joslarson 所述),但我认为它不是 完美强>(对我来说)。因为从一个键 (child
) 获取数据并将数据发送到另一个键 (child_id
) 对于 front-end强> 开发人员。 (完全没有冒犯)
所以,我在这里建议的是,重写 ParentSerializer
的 to_representation()
方法就可以了。
def to_representation(self, instance):
response = super().to_representation(instance)
response['child'] = ChildSerializer(instance.child).data
return response
序列化器的完整表示
class ChildSerializer(ModelSerializer):
class Meta:
model = Child
fields = '__all__'
class ParentSerializer(ModelSerializer):
class Meta:
model = Parent
fields = '__all__'
<b>def to_representation(self, instance):
response = super().to_representation(instance)
response['child'] = ChildSerializer(instance.child).data
return response</b>
Advantage of this method?
通过使用这种方法,我们不需要创建和读取两个单独的字段。这里创建和读取都可以使用child
键完成。
用于创建 parent
实例的示例负载
{
"name": "TestPOSTMAN_name",
"phone_number": 1,
"child": 1
}
关于python - DRF : Simple foreign key assignment with nested serializers?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29950956/