序列化 django rest 框架时的附加字段

Posted

技术标签:

【中文标题】序列化 django rest 框架时的附加字段【英文标题】:Additional field while serializing django rest framework 【发布时间】:2014-05-05 19:17:45 【问题描述】:

我是 django rest 框架的新手,并创建了一个示例 Employee 模型。

我的models.py

class Employees(models.Model):
    created = models.DateTimeField(auto_now_add=True)
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)

我的serializers.py

class EmployeeSerializer(serializers.Serializer):
    class Meta:
        model = Employees
        fields = ('first_name','last_name')

这很好,但我想要一个额外的字段full_name,它将是first_name + last_name

如何在我的serializers.py 中定义这个新字段full_name

【问题讨论】:

【参考方案1】:

我在这里看到了两种方式(我更喜欢第一种方式,因为您可以在应用程序的其他部分重复使用它):

将计算属性添加到您的模型并将其添加到您的序列化程序中 通过使用a readonly field with source=

# models.py
class Employees(models.Model):
    created = models.DateTimeField(auto_now_add=True)
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)

    @property
    def full_name(self):
        return self.first_name + self.last_name

# serializers.py
class EmployeeSerializer(serializers.ModelSerializer):
    full_name = serializers.Field(source='full_name')

    class Meta:
        model = Employees
        fields = ('first_name','last_name', 'full_name')

使用SerializerMethodField (您的模型不变)

class EmployeeSerializer(serializers.ModelSerializer):
    full_name = serializers.SerializerMethodField('get_full_name')

    def get_full_name(self, obj):
        return obj.first_name + obj.last_name

    class Meta:
        model = Employees
        fields = ('first_name','last_name', 'full_name')

【讨论】:

对我来说,使用serializers.Field 会出错。如果未定义 to_representation 并且视图是只读的,serializers.ReadOnlyField 确实有效。 我刚刚遇到了同样的问题(我不是序列化 Django 模型,而是另一个普通类),在我头疼了一段时间之后,我发现如果你使用它就可以正常工作full_name = serializers.ReadOnlyField(),即完全丢弃source参数。正如documentation says 关于source 参数:它默认为字段的名称。 Ans 即使它是一个方法(或一个属性),它也可以工作 对我来说(django 1.11.13)不需要在序列化器中声明字段,只需在Model中声明并在Meta.fields中列出即可。【参考方案2】:

SerializerMethodField 工作正常,我们也可以将数据存储在序列化器对象中,让方法get_field_name 使用它。

例子:

class MySerializer(serializers.ModelSerializer):
    statistic = serializers.SerializerMethodField()

    def __init__(self, instance=None, data=serializers.empty, statistic=None, **kwargs):
        super(MySerializer, self).__init__(instance=instance, data=data, **kwargs)
        self.statistic = statistic

    def get_statistic(self, obj):
        if self.statistic is None:
            return serializers.empty
        return self.statistic.get(obj.id, )

【讨论】:

【参考方案3】:

假设Employee是登录用户,那么我们大多数人都会使用django.auth.User,我将分享Employee如何实现为另一个Profile(django用户的扩展)。还添加了full_name.read_onlyfirst_name.write_onlylast_name.write_only

# models.py
class Employee(models.Model):
    """User Profile Model"""
    user = models.OneToOneField('auth.User')

# serializers.py
class EmployeeSerializer(serializers.HyperlinkedModelSerializer):
    username = serializers.CharField(source='user.username')
    email = serializers.EmailField(source='user.email')

    first_name = serializers.CharField(
            source='user.first_name', write_only=True)
    last_name = serializers.CharField(
            source='user.last_name', write_only=True)
    name = serializers.CharField(
            source='user.get_full_name', read_only=True)


    class Meta:
        model = Employee
        fields = (
            'url', 'username', 'email',
            'first_name', 'last_name', 'name')
        depth = 1

【讨论】:

以上是关于序列化 django rest 框架时的附加字段的主要内容,如果未能解决你的问题,请参考以下文章

在django rest framework的model序列化时,字段有可能是None时的处理办法

python Django Rest_Framework框架 模型类序列化器(ModelSerializer)详解(图文并茂版)

python Django Rest_Framework框架 模型类序列化器(ModelSerializer)详解(图文并茂版)

如何从序列化器字段订购 django rest 框架查询集?

Django rest框架 - 模型序列化程序不会序列化所有字段

如何在 django rest 框架中为枚举字段创建序列化程序