我有一个带有字段tool_class的模型,它的详细名称是class,与名称不同:
class Tool(models.Model):
tool_class = jsonfield.JSONField(verbose_name="class")序列化程序和ViewSet只是股票HyperlinkedModelSerializer和ModelViewSet。
因此,当我用键class向服务器发布或放置数据时,就可以识别它:
'{"class": "..."}但是在响应数据中,它又被称为tool_class:
{"tool_class": "..."}如何使它永远被称为class?
我不能为字段名使用名称"class",因为它在python中是一个保留字,但是在"class"中它绝对必须被称为"class",因为它符合指定这个单词的某种开放标准。
显然,我不能说:
class = CharField(source="tool_class")在我的ToolSerializer中,因为它是一个SyntaxError: invalid syntax。
简单解决方案:另一个线程中的人员提出了一个很好的解决方案。您可以使用vars()语法来解决这个问题。例如,我使用以下代码:
class Tool(Document):
vars()['class'] = mongoengine.fields.DictField(required=True)序列化程序自动创建各自的字段。我们是不是偷偷摸摸的?
发布于 2016-07-12 11:25:54
您可以通过重写序列化程序的元类来做到这一点。下面是一个serializers.py文件的示例。
主要的魔法是元类的这一部分。
# 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属性时,从名称中移除下划线。
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发布于 2016-05-23 17:38:02
我试图在序列化程序上使用一些技巧,在序列化程序上找到一个名为class的字段,但是它变得非常麻烦和讨厌。在将字段绑定到序列化程序时,field_name是从字段中收集的,因此无法轻松地覆盖绑定的行为。
最后,我决定让DRF完成它的工作,并在序列化程序上添加一个后处理步骤,这样会更好、更简单:
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:
data = OrderedDict(
('class' if k == 'tool_class' else k, v) for (k, v) in data.items()
)https://stackoverflow.com/questions/37394294
复制相似问题