Django REST Framework: добавление дополнительного поля в ModelSerializer
Я хочу сериализовать модель, но хочу включить дополнительное поле, которое требует выполнения некоторых запросов базы данных на экземпляре модели для сериализации:
class FooSerializer(serializers.ModelSerializer):
my_field = ... # result of some database queries on the input Foo object
class Meta:
model = Foo
fields = ('id', 'name', 'myfield')
Каков правильный способ сделать это? Я вижу, что вы можете передать дополнительный "контекст" в сериализатор, является ли правильным ответом на переход в дополнительное поле в словаре контекста? При таком подходе логика получения нужного поля не будет самодостаточной с определением сериализатора, что идеально, поскольку каждый сериализованный экземпляр понадобится my_field
. В другом месте документации документаторов серии DRF говорит "дополнительные поля могут соответствовать любому свойству или вызываемому на модели". Есть лишние поля, о чем я говорю? Должен ли я определить функцию в определении модели Foo
, которая возвращает значение my_field
, а в сериализаторе я подключаю my_field к этому вызываемому? Как это выглядит?
Заранее благодарим, если вам необходимо, прояснить вопрос.
Ответы
Ответ 1
Я думаю, что SerializerMethodField - это то, что вы ищете:
class FooSerializer(serializers.ModelSerializer):
my_field = serializers.SerializerMethodField('is_named_bar')
def is_named_bar(self, foo):
return foo.name == "bar"
class Meta:
model = Foo
fields = ('id', 'name', 'my_field')
http://www.django-rest-framework.org/api-guide/fields/#serializermethodfield
Ответ 2
Вы можете изменить свой метод модели на свойство и использовать его в сериализаторе с таким подходом.
class Foo(models.Model):
. . .
@property
def my_field(self):
return stuff
. . .
class FooSerializer(ModelSerializer):
my_field = serializers.ReadOnlyField(source='my_field')
class Meta:
model = Foo
fields = ('my_field',)
Изменить: в последних версиях системы отдыха (я пробовал 3.3.3) вам не нужно менять свойство. Метод модели будет работать нормально.
Ответ 3
Мой ответ на аналогичный вопрос (здесь) может оказаться полезным.
Если у вас есть метод модели, определенный следующим образом:
class MyModel(models.Model):
...
def model_method(self):
return "some_calculated_result"
Вы можете добавить результат вызова указанного метода к вашему сериализатору следующим образом:
class MyModelSerializer(serializers.ModelSerializer):
model_method_field = serializers.CharField(source='model_method')
p.s. Поскольку пользовательское поле на самом деле не является полем в вашей модели, вы, как правило, хотите сделать его доступным только для чтения, например:
class Meta:
model = MyModel
read_only_fields = (
'model_method_field',
)
Ответ 4
В последней версии Django Rest Framework вам необходимо создать метод в вашей модели с именем поля, которое вы хотите добавить. Нет необходимости в @property
и source='field'
вызывать ошибку.
class Foo(models.Model):
. . .
def foo(self):
return 'stuff'
. . .
class FooSerializer(ModelSerializer):
foo = serializers.ReadOnlyField()
class Meta:
model = Foo
fields = ('foo',)