DRF:序列化程序中的静态/只读/非模型字段?

时间:2014-11-20 18:20:11

标签: django django-rest-framework

是否可以在模型序列化器中包含静态字段?例如,我有一个模型:

class Location(models.Model):
    long = models.FloatField(...)
    lat = models.FloatField(...)

和一个序列化器:

class LocationSerialiser(serializers.ModelSerializer):
    class Meta:
        model = Location
        fields = ("id", "long", "lat")

使用简单的ListAPIView我可以看到我的所有位置:

{
    'id': 1,
    'long': ...,
    'lat': ...,
}, 
...

但是我想在我的json响应中为所有对象添加一个静态的非模型字段?类似的东西:

{
    'id': 1,
    'long': ...,
    'lat': ...,
    'display': True,
    'icon': 'image/marker.png'
}, 
...

如何将这些添加到序列化程序?我已经浏览了fields模块(2.2.4),但我没有看到任何明确的方法来实现这一目标。一切都需要source属性。

理想情况下我想做

class LocationSerialiser(serializers.ModelSerializer):
    display = fields.BooleanField(value=True)
    icon = fields.CharField(value="image/marker.png")

    class Meta:
        model = Location
        fields = ("id", "long", "lat")

修改

我发现的一种方法是在模型实例上简单地添加额外的@property包装方法:

class Location(models.Model):
    long = models.FloatField(...)
    lat = models.FloatField(...)

    @property
    def show(self):
        return True

    ...

然后在序列化器中:

class LocationSerialiser(serializers.ModelSerializer):
    display = fields.BooleanField(value=True)
    icon = fields.CharField(value="image/marker.png")

    show = fields.CharField(source="show")

    class Meta:
        model = Location
        fields = ("id", "long", "lat")

但这似乎非常hacky。必须有一个更清洁的方法来实现这一目标吗?

1 个答案:

答案 0 :(得分:4)

如果此字段是模型上的属性或方法(例如get_full_name),则可以在序列化器字段上指定自定义source。 Django REST Framework将自动检测它们是方法,并仍然会调用并显示它们。

class Location(models.Model):
    # ...

    def display(self):
        return True

    def icon(self):
        return "image/marker.png"

class LocationSerialiser(serializers.ModelSerializer):
    display = serializers.BooleanField(read_only=True)
    icon = serializers.CharField(read_only=True)

    class Meta:
        model = Location
        fields = ("id", "long", "lat", "display", "icon", )

如果您不能或不想将该函数放在模型上,Django REST Framework会a SerializerMethodField调用序列化程序中的一个方法,该方法可以返回将要显示的数据。

class LocationSerialiser(serializers.ModelSerializer):
    display = serializers.SerializerMethodField("get_display")
    icon = serializers.SerializerMethodField("get_icon")

    class Meta:
        model = Location
        fields = ("id", "long", "lat", "display", "icon", )

    def get_display(self, obj):
        return True

    def get_icon(self, obj):
        return "image/marker.png"