100

我创建了一个ModelSerializer并想添加一个不属于我的模型的自定义字段。

我在这里找到了添加额外字段的描述,并尝试了以下方法:

customField = CharField(source='my_field')

当我添加这个字段并调用我的validate()函数时,这个字段不是attr字典的一部分。attr包含除额外字段外指定的所有模型字段。所以我无法在覆盖验证中访问此字段,可以吗?

当我像这样将此字段添加到字段列表时:

class Meta:
    model = Account
    fields = ('myfield1', 'myfield2', 'customField')

然后我得到一个错误,因为customField它不是我的模型的一部分 - 什么是正确的,因为我只想为这个序列化程序添加它。

有没有办法添加自定义字段?

4

8 回答 8

93

事实上,有一个完全不接触模型的解决方案。您可以使用SerializerMethodField它允许您将任何方法插入序列化程序。

class FooSerializer(ModelSerializer):
    foo = serializers.SerializerMethodField()

    def get_foo(self, obj):
        return "Foo id: %i" % obj.pk
于 2016-09-14T11:14:58.737 回答
66

您正在做正确的事情,除了CharField(和其他类型的字段)用于可写字段。

在这种情况下,您只需要一个简单的只读字段,因此只需使用:

customField = Field(source='get_absolute_url')
于 2013-01-29T13:38:57.120 回答
18

...为清楚起见,如果您有以下方式定义的模型方法:

class MyModel(models.Model):
    ...

    def model_method(self):
        return "some_calculated_result"

您可以将调用所述方法的结果添加到您的序列化程序,如下所示:

class MyModelSerializer(serializers.ModelSerializer):
    model_method_field = serializers.CharField(source='model_method')

ps 由于自定义字段实际上不是模型中的字段,因此您通常希望将其设为只读,如下所示:

class Meta:
    model = MyModel
    read_only_fields = (
        'model_method_field',
        )
于 2015-04-06T16:56:44.430 回答
14

这里回答你的问题。您应该添加到您的模型帐户:

@property
def my_field(self):
    return None

现在您可以使用:

customField = CharField(source='my_field')

来源:https ://stackoverflow.com/a/18396622/3220916

于 2014-01-21T22:21:10.690 回答
12

为了显示self.author.full_name,我遇到了一个错误Field。它适用于ReadOnlyField

class CommentSerializer(serializers.HyperlinkedModelSerializer):
    author_name = ReadOnlyField(source="author.full_name")
    class Meta:
        model = Comment
        fields = ('url', 'content', 'author_name', 'author')
于 2016-09-02T05:29:42.120 回答
7

使用最新版本的 Django Rest Framework,您需要在模型中创建一个方法,并使用您要添加的字段的名称。

class Foo(models.Model):
    . . .
    def foo(self):
        return 'stuff'
    . . .

class FooSerializer(ModelSerializer):
    foo = serializers.ReadOnlyField()

    class Meta:
        model = Foo
        fields = ('foo',)
于 2016-06-30T14:21:48.557 回答
6

我正在寻找一种将可写自定义字段添加到模型序列化程序的解决方案。我找到了这个,这个问题的答案中没有涉及到。

看来您确实需要编写自己的简单序列化程序。

class PassThroughSerializer(serializers.Field):
    def to_representation(self, instance):
        # This function is for the direction: Instance -> Dict
        # If you only need this, use a ReadOnlyField, or SerializerField
        return None

    def to_internal_value(self, data):
        # This function is for the direction: Dict -> Instance
        # Here you can manipulate the data if you need to.
        return data

现在您可以使用此 Serializer 将自定义字段添加到 ModelSerializer

class MyModelSerializer(serializers.ModelSerializer)
    my_custom_field = PassThroughSerializer()

    def create(self, validated_data):
        # now the key 'my_custom_field' is available in validated_data
        ...
        return instance

如果模型MyModel实际上有一个名为的属性my_custom_field但您想忽略它的验证器,这也有效。

于 2019-10-07T17:05:40.310 回答
6

在这里阅读所有答案后,我的结论是不可能干净地做到这一点。您必须玩弄脏东西并做一些像创建 write_only 字段这样的事情,然后覆盖validateandto_representation方法。这对我有用:

class FooSerializer(ModelSerializer):

    foo = CharField(write_only=True)

    class Meta:
        model = Foo
        fields = ["foo", ...]

    def validate(self, data):
        foo = data.pop("foo", None)
        # Do what you want with your value
        return super().validate(data)

    def to_representation(self, instance):
        data = super().to_representation(instance)
        data["foo"] = whatever_you_want
        return data
于 2020-08-12T16:17:19.237 回答