Вопрос:
Я хочу сериализовать модель, но хочу включить дополнительное поле, которое требует выполнения некоторых запросов базы данных на экземпляре модели для сериализации:
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 к этому вызываемому? Как это выглядит?
Заранее благодарим, если вам необходимо, прояснить вопрос.
Лучший ответ:
Я думаю, что 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
Ответ №1
Вы можете изменить свой метод модели на свойство и использовать его в сериализаторе с таким подходом.
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) вам не нужно менять свойство. Метод модели будет работать нормально.
Ответ №2
Мой ответ на аналогичный вопрос (здесь) может оказаться полезным.
Если у вас есть метод модели, определенный следующим образом:
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’, ) Ответ №3
В последней версии 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’,)