使用模型属性的 ModelSerializer

Posted

技术标签:

【中文标题】使用模型属性的 ModelSerializer【英文标题】:ModelSerializer using model property 【发布时间】:2013-06-08 14:23:05 【问题描述】:

我正在尝试序列化包含我也想序列化的属性字段的模型。

models.py:

class MyModel(models.Model):
    name = models.CharField(max_length=100)
    slug = models.AutoSlugField(populate_from='name')

    @property
    def ext_link(self):
        return "/".join([settings.EXT_BASE_URL, self.slug])

serializers.py:

class MyModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = MyModel
        fields = ('name', 'ext_link')

在尝试访问相关 URL 时,我在 ext_link 属性上遇到了序列化程序异常 (KeyError)。

如何序列化ext_link 属性?

【问题讨论】:

【参考方案1】:

因为不是模型字段,所以需要显式添加到序列化器类中

class MyModelSerializer(serializers.ModelSerializer):
    ext_link = serializers.Field()

    class Meta:
        model = MyModel
        fields = ('name', 'ext_link')

【讨论】:

注意事项:Meta中的字段列表是可选的。如果您省略fields,在上面的示例中,您将获得序列化数据中的所有MyModel 字段加上ext_link。这对于复杂的模型来说真的很棒! 编辑:至少,djangorestframework==2.3.14 是这样。 对我来说,使用 serializers.Field 会出错。如果未定义 to_representation 并且视图是只读的,则“serializers.ReadOnlyField”确实有效。 我使用的是 3.3.x,仅仅向字段添加属性是不够的。我仍然必须通过 ext_link = serializers.ReadOnlyField() 显式添加。 在 Python 3.5.1 和 Django 1.10 上使用 DRF 3.4.6,添加到字段工作正常。 注意:使用 fields = "__all__" 我还必须添加 myfield = serializers.ReadOnlyField() 作为 jarmod 指定,使用版本 3.7.7【参考方案2】:

正如@Robert Townley的评论,这适用于版本3.8.2

class MyModelSerializer(serializers.ModelSerializer):
    ext_link = serializers.ReadOnlyField()

    class Meta:
        model = MyModel
        fields = "__all__"

【讨论】:

【参考方案3】:

接受的答案似乎对我不起作用,ReadOnlyField 也不起作用。

但是,当我使用与我的属性函数的返回类型相对应的字段时,我取得了成功。

例如,我会这样做:

class MyModelSerializer(serializers.ModelSerializer):
    ext_link = serializers.CharField()

    class Meta:
        model = MyModel
        fields = ('name', 'ext_link')

ListFieldDictFieldIntegerField 也可以做到这一点。

【讨论】:

最佳答案!!!

以上是关于使用模型属性的 ModelSerializer的主要内容,如果未能解决你的问题,请参考以下文章

使用枚举作为领域模型的属性

使用注释而不是模型属性

使用模型属性的 ModelSerializer

如何保护 Laravel 模型属性

MongoDB - 连接模型中的两个属性并使用结果更新模型

使用 lambda 而不是字符串属性名称选择模型属性