Sie müssen das Attribut class
nicht benennen, was zu allen Arten von Problemen führen kann. Sie können das Attribut class_
benennen, es jedoch weiterhin von einem Quellattribut namens class
abrufen und als class
in JSON rendern.
Sie können dies tun, indem Sie die Metaklasse für Serializer überschreiben. Hier ist ein Beispiel für eine serializers.py
Datei (die Modelle und Klassen werden weitgehend direkt aus der tutorial gezogen).
Die Haupt Magie ist dieser Abschnitt der metaclass
# Remap fields (to use class instead of class_)
fields_ = []
for name, field in fields:
if name.endswith('_'):
name = name.rstrip('_')
fields_.append((name, field))
Dieses beliebiges Feld Sie in dem Serializer definieren nimmt, die in einem Unterstrich endet (dh. field_
) und entfernt den Unterstrich vom Namen, wenn es das bindet Fields
und setzt das Attribut _declared_fields
auf dem Serializer. Hier
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 SnippetSerializer(serializers.Serializer):
__metaclass__ = MyMeta
pk = serializers.IntegerField(read_only=True)
title = serializers.CharField(required=False, allow_blank=True, max_length=100)
class_ = serializers.CharField(source='klass', label='class', default='blah')
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.title = validated_data.get('title', instance.title)
instance.class_ = validated_data.get('class', instance.class_)
instance.save()
return instance
ist die models.py Datei als Referenz (django erlaubt keine Feldnamen in einem Unterstrich zu enden)
from django.db import models
class Snippet(models.Model):
title = models.CharField(max_length=100, blank=True, default='')
klass = models.CharField(max_length=100, default='yo')
Dies ist, wie es aussieht von der django Shell
$ python manage.py shell
>>> from snippets.models import Snippet
>>> from snippets.serializers import SnippetSerializer
>>> from rest_framework.renderers import JSONRenderer
>>> from rest_framework.parsers import JSONParser
>>> snippet = Snippet(title='test')
>>> snippet.save()
>>> serializer = SnippetSerializer(snippet)
>>> serializer.data
{'title': u'test', 'pk': 6, 'class': u'yo'}
Sie können es nicht tun, technisch gibt es diese Klasse noch nicht (und Sie können nicht Bezug nehmen auf etwas, das noch nicht existiert). –
* "Ich muss eine Klassenvariable namens" class "definieren" * - "Need" ist ein starkes Wort für etwas, das Sie nicht tun sollten, weil Sie ein reserviertes Schlüsselwort verwenden ... – deceze
@deceze I ' Ich stimme Ihnen ansonsten völlig zu, aber 'MyClass' ist leider ein DRF-Serializer, der einen REST-Endpunkt darstellt. Ich implementiere ein bestimmtes Protokoll, das ein bestimmtes Feld mit dem Namen 'class' auf diesem REST-Endpunkt benötigt, und DRF erlaubt es nicht, dass sich der Feldname von seiner Darstellung in JSON unterscheidet. Also muss ich es definieren. Dies ist definitiv ein besserer Weg, als mit 'to_intern_value()/to_representation()' Methoden zu verfahren. –