我想序列化一个模型,但想包括一个额外的字段,需要在模型实例上做一些数据库查询要序列化:

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值的函数,并在序列化器中将my_field连接到该可调用对象?它看起来像什么?

如果有必要,我很乐意澄清问题。


当前回答

我对类似问题的回答可能会有用。

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

class MyModel(models.Model):
    ...

    def model_method(self):
        return "some_calculated_result"

你可以像这样将调用该方法的结果添加到你的序列化器中:

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

附注:因为自定义字段在你的模型中并不是一个真正的字段,你通常会想让它只读,像这样:

class Meta:
    model = MyModel
    read_only_fields = (
        'model_method_field',
        )

其他回答

如果你想为每个对象动态添加字段,你可以使用to_representation。

class FooSerializer(serializers.ModelSerializer):
  class Meta:
        model = Foo
        fields = ('id', 'name',)
  
  def to_representation(self, instance):
      representation = super().to_representation(instance)
      if instance.name!='': #condition
         representation['email']=instance.name+"@xyz.com"#adding key and value
         representation['currency']=instance.task.profile.currency #adding key and value some other relation field
         return representation
      return representation

通过这种方式,您可以为每个obj动态添加键和值 希望你喜欢

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

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),您不需要更改属性。模型方法可以很好地工作。

在序列化器类中添加以下内容:

def to_representation(self, instance):
    representation = super().to_representation(instance)
    representation['package_id'] = "custom value"
    return representation

在上一个版本的Django Rest Framework中,你需要在你的模型中创建一个带有你想要添加的字段名的方法。不需要@property和source='field'会引发错误。

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

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

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

我对类似问题的回答可能会有用。

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

class MyModel(models.Model):
    ...

    def model_method(self):
        return "some_calculated_result"

你可以像这样将调用该方法的结果添加到你的序列化器中:

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

附注:因为自定义字段在你的模型中并不是一个真正的字段,你通常会想让它只读,像这样:

class Meta:
    model = MyModel
    read_only_fields = (
        'model_method_field',
        )