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

Tim*_*ony 5 django django-rest-framework

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

class Location(models.Model):
    long = models.FloatField(...)
    lat = models.FloatField(...)
Run Code Online (Sandbox Code Playgroud)

和一个序列化器:

class LocationSerialiser(serializers.ModelSerializer):
    class Meta:
        model = Location
        fields = ("id", "long", "lat")
Run Code Online (Sandbox Code Playgroud)

通过一个简单的操作,ListAPIView我可以看到我的所有位置:

{
    'id': 1,
    'long': ...,
    'lat': ...,
}, 
...
Run Code Online (Sandbox Code Playgroud)

但是假设我想将静态的非模型字段添加到 json 响应中的所有对象中?就像是:

{
    'id': 1,
    'long': ...,
    'lat': ...,
    'display': True,
    'icon': 'image/marker.png'
}, 
...
Run Code Online (Sandbox Code Playgroud)

如何将它们添加到序列化器中?我已经浏览了该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")
Run Code Online (Sandbox Code Playgroud)

编辑

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

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

    @property
    def show(self):
        return True

    ...
Run Code Online (Sandbox Code Playgroud)

然后在序列化器中:

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")
Run Code Online (Sandbox Code Playgroud)

但这看起来很老套。必须有一种更清洁的方法来实现这一目标吗?

Kev*_*own 5

如果此字段是模型上的属性或方法(例如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", )
Run Code Online (Sandbox Code Playgroud)

如果您不能或不想将该函数放在您的模型上,Django REST Framework 有一个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"
Run Code Online (Sandbox Code Playgroud)