Django REST Framework:向ModelSerializer添加其他字段

Django REST Framework: adding additional field to ModelSerializer

我想要序列化一个模型,但想要包含一个额外的字段,该字段需要对模型实例进行一些数据库查找以进行序列化:

1
2
3
4
5
class FooSerializer(serializers.ModelSerializer):
  my_field = ... # result of some database queries on the input Foo object
  class Meta:
        model = Foo
        fields = ('id', 'name', 'myfield')

正确的方法是什么?我看到您可以在额外的"上下文"中传递给序列化程序,在上下文字典中传递额外字段的正确答案是什么?使用这种方法,获得我需要的字段的逻辑不会与序列化程序定义独立,这是理想的,因为每个序列化实例都需要my_field。在DRF序列化程序文档的其他地方,它说"额外的字段可以对应于模型上的任何属性或可调用的"。我说的是额外领域吗?我是否应该在Foo的模型定义中定义一个返回my_field值的函数,在序列化程序中,我将自己的字段连接到该可调用的?那是什么样子的?

事先谢谢,如有必要,很乐意澄清问题。


我认为Serializermethodfield是您需要的:

1
2
3
4
5
6
7
8
9
class FooSerializer(serializers.ModelSerializer):
  my_field = serializers.SerializerMethodField('is_named_bar')

  def is_named_bar(self, foo):
      return foo.name =="bar"

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

http://www.django-rest-framework.org/api-guide/fields/serializermethodfield


您可以将模型方法更改为属性,并使用此方法在序列化程序中使用它。

1
2
3
4
5
6
7
8
9
10
11
12
13
class Foo(models.Model):
    . . .
    @property
    def my_field(self):
        return stuff
    . . .

class FooSerializer(ModelSerializer):
    my_field = serializers.ReadOnlyField(source='my_field')

    class Meta:
        model = Foo
        fields = ('my_field',)

编辑:使用最新版本的REST框架(我尝试了3.3.3),您不需要更改为属性。模型方法会很好地工作。


使用最后一个版本的django-rest框架,您需要在模型中创建一个方法,该方法具有要添加的字段的名称。不需要@propertysource='field'引起错误。

1
2
3
4
5
6
7
8
9
10
11
12
class Foo(models.Model):
    . . .
    def foo(self):
        return 'stuff'
    . . .

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

    class Meta:
        model = Foo
        fields = ('foo',)


我对类似问题的回答(这里)可能有用。

如果您有一个模型方法定义如下:

1
2
3
4
5
class MyModel(models.Model):
    ...

    def model_method(self):
        return"some_calculated_result"

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

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

另外,由于自定义字段在您的模型中不是真正的字段,所以您通常希望将其设置为只读,如:

1
2
3
4
5
class Meta:
    model = MyModel
    read_only_fields = (
        'model_method_field',
        )

如果您想对额外的字段进行读写,可以使用一个新的自定义序列化程序,它扩展了序列化程序.serializer,并像这样使用它

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class ExtraFieldSerializer(serializers.Serializer):
    def to_representation(self, instance):
        # this would have the same as body as in a SerializerMethodField
        return 'my logic here'

    def to_internal_value(self, data):
        # This must return a dictionary that will be used to
        # update the caller's validation data, i.e. if the result
        # produced should just be set back into the field that this
        # serializer is set to, return the following:
        return {
          self.field_name: 'Any python object made with data: %s' % data
        }

class MyModelSerializer(serializers.ModelSerializer):
    my_extra_field = ExtraFieldSerializer(source='*')

    class Meta:
        model = MyModel
        fields = ['id', 'my_extra_field']

我在相关的嵌套字段中使用它,其中包含一些自定义逻辑


This worked for me
.If we want to just add a additional field in ModelSerializer, we can
do it like below and also the field can be assigned some val after
some calculations of lookup. Or In some case if we want to send the
parameters in API response.

在model.py中

1
2
3
4
5
6
7
class Foo(models.Model):
   """Model Foo"""
    name = models.CharField(max_length=30, help_text="Customer Name")



   **

In serializer.py

**

1
2
3
4
5
6
7
8
9
10
11
class FooSerializer(serializers.ModelSerializer):
    retrieved_time = serializers.SerializerMethodField()

    @classmethod
    def get_retrieved_time(self, object):
       """getter method to add field retrieved_time"""
        return None

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

**

Hope this could help someone

**


正如化学程序员在评论中所说,在最新的DRF中,你可以这样做:

1
2
3
4
5
6
7
8
9
class FooSerializer(serializers.ModelSerializer):
    extra_field = serializers.SerializerMethodField()

    def get_extra_field(self, foo_instance):
        return foo_instance.a + foo_instance.b

    class Meta:
        model = Foo
        fields = ('extra_field', ...)

DRF文档源