如何在 Django REST 框架中更改字段名

我试图在 DRF 序列化程序中更改 Model 字段名,就像在 SQL 中更改别名一样。我尝试过不同的方法,但是不能成功。

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

序列化器 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/‘ module’对象的 AttributeError 没有属性‘ Field’

我怎么能这么做?

102600 次浏览

你可以使用 serializers.SerializerMethodField:

下面是 model Park,它具有 name 和 Alternate _ 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 的 Serializer ,ParkSerializer。

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

此外,还可以使用具有 source属性的 serializers.CharField:

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=...)和其他字段类型。

然而,这只对只读字段有效。

在序列化器字段和通常称为“源”的序列化器中有一个非常好的特性,您可以在其中指定来自模型字段的数据源。

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


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

序列化器。Some SerializerField 可以是序列化器。CharField 如您的模型所示,但也可以是其他任何字段。另外,您可以将关系字段和其他序列化器替换为关系字段和其他序列化器,这样仍然可以很好地工作。即使 other _ 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

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

这也适用于写操作

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


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

我知道这是近2年后,但认为它可能有助于任何未来的开发..。

代码无法工作的原因是由于 Models.py中的以下行
location = serializers.Field(source='alias_alternate_name')
这就是那个例外试图告诉我们的,那就是:
AttributeError at /ViewName/ 'module' object has no attribute 'Field'
意味着序列化器模块没有名为 Field的项。

我想提供一个不同于其他答案的解决方案:
修改 Models.py以包含 related _ name 字段,然后在序列化器中简单地使用此名称。

这种方法的优点是序列化程序中的字段名称和模型中的字段名称具有一对一的映射,代码较少,缺点是这种方法可能无法处理复杂的外键关系。

下面是我的方法的演示:

Models.py

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


class Meta:
db_table = u'p_park'

序列化器 py

class ParkSerializer(serializers.ModelSerializer):


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

点击这里阅读更多相关内容: http://strong > < a href = “ https://www.django-rest-framework.org/api-guide/relations/”rel = “ nofollow noReferrer”> https://www.django-rest-framework.org/api-guide/relations/

另一种方法

class UrlHyperlinkedModelSerializer(serializers.HyperlinkedModelSerializer):
field_name_map = {}


def to_representation(self, instance):
res = super().to_representation(instance)
nres = res.__class__()
for k, v in res.items():
nres[self.field_name_map.get(k, k)] = v
return nres


class CommentSerializer(UrlHyperlinkedModelSerializer):
field_name_map = {
'a': 'a_url'
}


class Meta:
model = models.Comment
fields = ['a', 'url', 'body', 'created_at']