首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Django REST框架:如何使字段的详细名称与其field_name不同?

Django REST框架:如何使字段的详细名称与其field_name不同?
EN

Stack Overflow用户
提问于 2016-05-23 14:55:45
回答 2查看 1.5K关注 0票数 6

我有一个带有字段tool_class的模型,它的详细名称是class,与名称不同:

代码语言:javascript
复制
class Tool(models.Model):
    tool_class = jsonfield.JSONField(verbose_name="class")

序列化程序和ViewSet只是股票HyperlinkedModelSerializerModelViewSet

因此,当我用键class向服务器发布或放置数据时,就可以识别它:

代码语言:javascript
复制
'{"class": "..."}

但是在响应数据中,它又被称为tool_class

代码语言:javascript
复制
{"tool_class": "..."}

如何使它永远被称为class

我不能为字段名使用名称"class",因为它在python中是一个保留字,但是在"class"中它绝对必须被称为"class",因为它符合指定这个单词的某种开放标准。

显然,我不能说:

代码语言:javascript
复制
class = CharField(source="tool_class")

在我的ToolSerializer中,因为它是一个SyntaxError: invalid syntax

简单解决方案:另一个线程中的人员提出了一个很好的解决方案。您可以使用vars()语法来解决这个问题。例如,我使用以下代码:

代码语言:javascript
复制
class Tool(Document):
    vars()['class'] = mongoengine.fields.DictField(required=True)

序列化程序自动创建各自的字段。我们是不是偷偷摸摸的?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-07-12 11:25:54

您可以通过重写序列化程序的元类来做到这一点。下面是一个serializers.py文件的示例。

主要的魔法是元类的这一部分。

代码语言:javascript
复制
# Remap fields (to use class instead of class_)
fields_ = []
for name, field in fields:
    if name.endswith('_'):
        name = name.rstrip('_')
    fields_.append((name, field))

这需要在序列化程序中以下划线结尾的任何字段(即。( field_),并在绑定Fields并在序列化程序上设置_declared_fields属性时,从名称中移除下划线。

代码语言:javascript
复制
from collections import OrderedDict

from rest_framework import serializers
from rest_framework.fields import Field
from snippets.models import Snippet, LANGUAGE_CHOICES, STYLE_CHOICES

class MyMeta(serializers.SerializerMetaclass):

    @classmethod
    def _get_declared_fields(cls, bases, attrs):
        fields = [(field_name, attrs.pop(field_name))
                  for field_name, obj in list(attrs.items())
                  if isinstance(obj, Field)]
        fields.sort(key=lambda x: x[1]._creation_counter)

        # If this class is subclassing another Serializer, add that Serializer's
        # fields.  Note that we loop over the bases in *reverse*. This is necessary
        # in order to maintain the correct order of fields.
        for base in reversed(bases):
            if hasattr(base, '_declared_fields'):
                fields = list(base._declared_fields.items()) + fields

        # Remap fields (to use class instead of class_)
        fields_ = []
        for name, field in fields:
            if name.endswith('_'):
                name = name.rstrip('_')
            fields_.append((name, field))

        return OrderedDict(fields_)


class ToolSerializer(serializers.Serializer):

    __metaclass__ = MyMeta

    ...
    class_ = serializers.JSONField(source='tool_class', label='class')

    def create(self, validated_data):
        """
        Create and return a new `Snippet` instance, given the validated data.
        """
        return Snippet.objects.create(**validated_data)

    def update(self, instance, validated_data):
        """
        Update and return an existing `Snippet` instance, given the validated data.
        """
        ...
        instance.class_ = validated_data.get('class', instance.class_)
        instance.save()
        return instance
票数 2
EN

Stack Overflow用户

发布于 2016-05-23 17:38:02

我试图在序列化程序上使用一些技巧,在序列化程序上找到一个名为class的字段,但是它变得非常麻烦和讨厌。在将字段绑定到序列化程序时,field_name是从字段中收集的,因此无法轻松地覆盖绑定的行为。

最后,我决定让DRF完成它的工作,并在序列化程序上添加一个后处理步骤,这样会更好、更简单:

代码语言:javascript
复制
class ToolSerializer(ModelSerializer):
    class Meta:
        model = Tool

    def to_representation(self, instance):
        data = super(ToolSerializer, self).to_representation(instance)
        data['class'] = data.pop('tool_class')
        return data

请注意,to_representation返回的数据结构是一个OrderedDict,这稍微干扰了排序--这个映射中重命名的键将从它所在的位置移除并推到后面。

对于大多数用例来说,这不太可能是一个问题,所以如果没有必要的话,您不应该费心去解决它。如果确实需要保留排序,请使用理解重新构建一个新的OrderedDict

代码语言:javascript
复制
data = OrderedDict(
    ('class' if k == 'tool_class' else k, v) for (k, v) in data.items()
)
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37394294

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档