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):
child = RelatedFieldAlternative(queryset=Child.objects.all(), serializer=ChildSerializer)
class Meta:
model = Parent
fields = '__all__'
原帖
使用两个不同的字段会ok(正如@Kevin Brown 和@joslarson 提到的),但我认为它不是完美强>(对我来说)。因为从一个键 (child) 获取数据并将数据发送到另一个键 (child_id) 对于 前端 开发人员来说可能有点模棱两可。 (完全没有冒犯)
所以,我在这里的建议是,重写 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__'
def to_representation(self, instance):
response = super().to_representation(instance)
response['child'] = ChildSerializer(instance.child).data
return response
这种方法的优点?
通过使用这种方法,我们不需要创建和读取两个单独的字段。在这里,创建和读取都可以使用 child 键完成。
用于创建 parent 实例的示例负载
{
"name": "TestPOSTMAN_name",
"phone_number": 1,
"child": 1
}
截图