如何在Django REST Framework中更改字段名称


93

我正在尝试像在SQL中的别名一样在DRF序列化器中更改“模型”字段名称。我尝试了不同的方法,但无法成功。

models.py

class Park(models.Model):
    name = models.CharField(max_length=256)
    alternate_name = models.CharField(max_length=256, blank=True)
    objects = models.GeoManager()

    class Meta:
        db_table = u'p_park'

    def __unicode__(self):
        return '%s' % self.name

    def alias_alternate_name(self):
        return self.alternate_name

serializers.py

class ParkSerializer(serializers.ModelSerializer):

    location = serializers.Field(source='alias_alternate_name')
    #location = serializers.SerializerMethodField(source='alias_alternate_name')

    #alternate_name as location


    class Meta:
        model = Park
        fields = ('id', 'name', 'location')

我也曾尝试在Django Queryset中添加别名,但无法更改。

更新

这是我面临的例外

/ ViewName /'模块'对象上的AttributeError没有属性'Field'

我怎样才能做到这一点?


1
您是否在使用正确的serializers.SerializerMethodField方法?我的意思是这样的:serializers.SerializerMethodField('get_location')def get_location(self, obj): ...
erthalion

我们可以看到进口serializers.py吗?
joerick 2014年

Answers:


56

您可以使用serializers.SerializerMethodField

这是 Park 模型,其中包含name和Alternative_name字段。

class Park(models.Model):
    name = models.CharField(max_length=256)
    alternate_name = models.CharField(max_length=256, blank=True)
    objects = models.GeoManager()

    class Meta:
        db_table = u'p_park'

    def __unicode__(self):
        return '%s' % self.name

这是 Park Model的序列化器ParkSerializer。这会将alternate_name的名称更改为location。

class ParkSerializer(serializers.ModelSerializer):
    location = serializers.SerializerMethodField('get_alternate_name')

    class Meta:
        model = Park
        fields = ('other_fields', 'location')

    def get_alternate_name(self, obj):
        return obj.alternate_name

此外,您可以使用serializers.CharFieldwith source属性:

class ParkSerializer(serializers.ModelSerializer):
    location = serializers.CharField(source='other_fields')

    class Meta:
        model = Park
        fields = ('other_fields', 'location')

Django __遍历外键的符号也可以使用:

location = serializers.CharField(source='OtherModel__other_fields')

如果要更改API的返回类型,则适用相同的原理,因此也可以执行serializers.DecimalField(source=...)其他字段类型。

但是,这仅适用于只读字段。


现在,此异常在/ ViewName /'模块'对象上没有属性'SerializerMethodField'时
引发

1
此锻炼如何创建和编辑请求?
iankit

1
“ Python禅”的第13行:“应该有一种-最好只有一种-显而易见的方法。”
iankit

13
这不应是公认的答案。请参阅下面的一个,在我撰写本文时,它的投票几乎是它的5倍。
cderwin

5
这是一个不好的解决方案。source如下所述,使用kwarg。
Patrick

212

序列化程序字段中有一个很好的功能,而序列化程序通常称为“源”,您可以从模型字段中指定数据源。

class ParkSerializer(serializers.ModelSerializer):
    location = serializers.SomeSerializerField(source='alternate_name')

    class Meta:
        model = Park
        fields = ('other_fields', 'location')

如模型所建议的,其中serializers.SomeSerializerField可以是serializers.CharField,但也可以由其他任何字段组成。您也可以放置关系字段和其他序列化器,这仍然可以像魅力一样工作。即,即使alternate_name是另一个模型的外键字段。

class ParkSerializer(serializers.ModelSerializer):
    locations = AlternateNameSerializer(source='alternate_name', many=true)

    class Meta:
        model = Park
        fields = ('other_fields', 'locations')

class AlternateNameSerializer(serializers.ModelSerialzer):
    class Meta:
        model = SomeModel

这也适用于请求的创建,删除和修改类型。它有效地创建了序列化程序中字段名称和模型中字段名称的一对一映射。


我同意,这source是更通用的方法。但是您在问题中几乎看不到有使用它的尝试,因此,如果您想以这种方式回答,则还应该弄清楚为什么原始代码不起作用,不是吗?
erthalion '16

您的代码将正常工作..只要请求用于列表和检索
iankit '16

这两个答案都不完整。对于外键,此方法意味着在创建新的Park时,您必须在POST请求中将整个父对象(alternate_name)作为字典,这是疯狂的,因为该父对象已经存在。一个人应该能够通过其ID提及外部实例。
stelios

就我而言(外键),我用解决了这个问题locations = serializers.PrimaryKeyRelatedField(source='alternate_name', queryset=AlternateName.objects.all())。显然RelatedField也可以使用。
stelios

@chefarov source ='new_name'是您可以给序列化程序字段,关系和其他相关的序列化程序等提供的通用参数。不确定为什么您说的答案不完整。
iankit

14

这也适用于写操作

class ParkSerializer(serializers.ModelSerializer):
    location = serializers.CharField(source='alternate_name')

    class Meta:
        model = Park
        fields = ('id', 'name', 'location')
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.