我有两个具有外键关系的简单模型,如下所示:
class Foo(models.Model):
code = models.CharField(max_length=255)
class Bar(models.Model):
foo = models.ForeignKey(Foo)
description = models.CharField(max_length=255)
当前基于rest_framework
的序列化器如下所示:
class FooSerializer(serializers.ModelSerializer):
class Meta:
model = models.Foo
fields = ('id', 'code')
class BarSerializer(serializers.ModelSerializer):
class Meta:
model = models.Bar
fields = ('id', 'foo', 'description')
因此,对Bar
的GET请求将返回如下内容:
{
"id": 1,
"foo": 2,
"description": "[…]"
}
如何更改BarSerializer
以代替返回完整的Foo
对象,,如下所示:
{
"id": 1,
"foo": {
"id": 2,
"code": "[…]"
},
"description": "[…]"
}
?
请记住,我仍然需要仅提供Bar
和description
ID来创建Foo
。我尝试了各种操作,包括在foo = FooSerializer()
中指定BarSerializer
。问题是,当我想像以前一样创建新的Bar
并将其链接到现有的 Foo
时,它抱怨我没有提供Foo
的code
属性。
答案 0 :(得分:1)
以
to_represention()
方法
class BarSerializer(serializers.ModelSerializer):
class Meta:
model = models.Bar
fields = ('id', 'foo', 'description')
def to_representation(self, instance):
data = super().to_representation(instance)
data['foo'] = FooSerializer(instance.foo).data
return data
在 depth=1
序列化程序中使用 BarSerializer
class BarSerializer(serializers.ModelSerializer):
class Meta:
model = models.Bar
fields = ('id', 'foo', 'description')
depth = 1
参考
1. depth
[DRF-Doc]
Update-1
将 两个不同的序列化器 用于读取和写入操作。
class BarWriteSerializer(serializers.ModelSerializer):
class Meta:
model = Bar
fields = ('id', 'foo', 'description')
def to_representation(self, instance):
data = super().to_representation(instance)
data['foo'] = FooSerializer(instance.foo).data
return data
class BarReadSerializer(serializers.ModelSerializer):
class Meta:
model = Bar
fields = ('id', 'foo', 'description')
depth = 1
,然后在您的视图中,将 get_serializer_class()
方法替换为
from rest_framework import viewsets
class SampleViewset(viewsets.ModelViewSet):
queryset = Bar.objects.all()
def get_serializer_class(self):
if self.action == 'create':
return BarWriteSerializer
return BarReadSerializer
Bar
创建时要使用的有效载荷,
{
"foo":1,# The "pk" of "Foo" instance
"description":"bar description"
}
答案 1 :(得分:0)
解决方案:
class FooSerializer(serializers.ModelSerializer):
class Meta:
model = models.Foo
fields = ('id', 'code')
class BarSerializer(serializers.ModelSerializer):
foo = FooSerializer(models.Foo.objects.all(), read_only=True)
foo_id = serializers.PrimaryKeyRelatedField(
source='foo',
queryset=models.Foo.objects.all(),
write_only=True
)
class Meta:
model = models.Bar
fields = ('id', 'foo', 'foo_id', 'description')
使用嵌套的序列化程序作为read_only
来获取完整的Foo
对象。
使用write_only
字段foo_id
将其用于创建/更新。
现在,您的请求数据将如下所示:
{ 'foo_id': 1, 'description': 'foo bar' }
或者,如果您不需要两个字段,一个字段用于读取,另一个字段用于写入,则可以覆盖序列化程序的create
/ update
方法来捕获foo
的ID
示例:
class BarSerializer(serializers.ModelSerializer):
foo = FooSerializer(Foo.objects.all())
class Meta:
model = models.Bar
fields = ('id', 'foo', 'description')
def create(self, validated_data):
foo = validated_data.pop('foo')
bar = Bar.objects.create(
foo=foo.id,
**validated_data
)
return bar
def update(self, instance, validated_data):
foo = validated_data.pop('foo')
instance.foo = foo
instance.update(
**validated_data
)
return instance
在这种情况下,请求数据将是:
{ 'foo': {'id': '1', 'code': 'AAA'}, 'description': 'foo bar' }