Django反序列化一个字段但序列化另一个字段

时间:2021-05-04 09:05:48

标签: django django-rest-framework django-serializer

我有两个模型。 Bar 通过外键与 Foo 相关联。在我的 Bar 序列化器中,我有 FooSerializer,因此它可以从其模型中序列化:

class BarSerializer(serializers.ModelSerializer):
    foo = FooSerializer(source='*')
    ...
    class Meta:
        model = Bar

然后我的 Foo Serializer 看起来像:

class FooSerializer(serializers.ModelSerializer):
    name = serializers.StringRelatedField()
    link = serializers.SerializerMethodField()

    class Meta:
        model = Foo
        fields = ('name', 'link')

    def to_internal_value(self, data):
        # Save depending on name
        foo = Foo.objects.get(name=data)
        return {'foo': foo}

    def get_link(self, object):
        print('req', object.id)
        if object.id and request:
            return request.build_absolute_uri(
                '/app/foo/{}'.format(object.id))
        return None

我希望能够使用 Foo 的 name 字段在 Bar 中发帖,例如:

{
"bar_name": "Nikko",
"foo": "The Foo",
}

但我想要的回应是:

{
"bar_name": "Nikko",
"foo": {
      "name": "The Foo",
      "link": "https://localhost:8000/apps/foo/1",
      }
}

2 个答案:

答案 0 :(得分:1)

这是可能的。您需要将一个字段设为只写,而将另一个设为只读:

class BarSerializer(serializers.ModelSerializer):
    foo = FooSerializer(source='*', read_only=True)
    foo_write = serializers.SlugRelatedField(slug_field='name', queryset=Foo.objects.all(), write_only=True)
    ...
    class Meta:
        model = Bar

我使用 SlugRelatedField,它可以让您使用 name 属性来搜索 Foo 实例。它假定 Name 字段是唯一的,否则您将无法检索到正确的实例。

您可能需要在 source="Foo" 上添加 SlugRelatedField,如果它不能重新识别它所指的字段。

答案 1 :(得分:0)

如果您想要自定义响应,则必须覆盖 to_represendation(self, instance)drf-doc

更新

如果您想添加额外的 context 并从 request 获取信息,您可以这样添加

add extra context

serializer = FooSerializer(..., context={'request': request})

获取请求数据,在您的 self.context 中使用 to_representation()

相关问题