Bor*_*kov 6 python django django-rest-framework
我有一个带有 field 的模型tool_class,其详细名称class与 name 不同:
class Tool(models.Model):
tool_class = jsonfield.JSONField(verbose_name="class")
Run Code Online (Sandbox Code Playgroud)
Serializer 和 ViewSet 只是库存HyperlinkedModelSerializer和ModelViewSet.
因此,当我使用 key 将数据 POST 或 PUT 数据发送到服务器时class,可以很好地识别:
'{"class": "..."}
Run Code Online (Sandbox Code Playgroud)
但在响应数据中它tool_class再次被调用:
{"tool_class": "..."}
Run Code Online (Sandbox Code Playgroud)
如何让它一直被调用class?
我不能使用"class"字段名称的名称,因为它是python中的保留字,但在API中绝对必须调用它"class",因为API符合某个开放标准,该标准指定了这个词。
显然,我不能说:
class = CharField(source="tool_class")
Run Code Online (Sandbox Code Playgroud)
在 my 中ToolSerializer,因为它是一个SyntaxError: invalid syntax.
简单的解决方案:
另一个线程中的人提出了一个很好的解决方案。您可以使用vars()语法来规避此问题。例如,我使用以下代码:
class Tool(Document):
vars()['class'] = mongoengine.fields.DictField(required=True)
Run Code Online (Sandbox Code Playgroud)
序列化程序自动创建相应的字段。我们不是偷偷摸摸的吗?
您可以通过覆盖序列化器的元类来做到这一点。这是一个文件的示例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))
Run Code Online (Sandbox Code Playgroud)
这采用您在序列化器中定义的以下划线(即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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1265 次 |
| 最近记录: |