Ответ 1
Вам действительно нужно разделить вещи между представлениями и сериализатором.
сериализаторы
Serializer
является автономным объектом. Он используется для преобразования модели Django (или любой структуры данных python, фактически) в сериализованную форму и наоборот.
Вы можете использовать его как таковое, где хотите. Ему даже не нужен фактический HTTP-запрос, если вам не нужны URI в вашем выпуске.
Подкласс ModelSerializer
- это специализированный вид Serializer
, который добавляет функциональность "load-from-model" и "save-to-model".
Точкой входа "save-to-model" является метод save()
. Для упрощения переопределения его реализация по умолчанию будет делегировать свою работу методу create()
или update()
для сериализатора, в зависимости от того, создает ли он экземпляр новой модели или обновляет его.
Целью этой настройки является настройка: она дает разработчику возможность переопределить только метод create, просто метод обновления или общее поведение. Например, он позволяет вам делать такие вещи:
def save(self, **kwargs):
# Will be done on every save
kwargs['last_changed'] = timezone.now()
return super().save(**kwargs)
def create(self, instance, data):
# Will only be done if a new object is being created
data['initial_creation'] = timezone.now()
return super().create(instance, data)
Это базовый пример. Там поле last_changed
будет устанавливаться каждый раз, когда объект будет сохранен, будь то создание или обновление.
Как побочный элемент, вы, вероятно, не хотите этого делать. Такие вещи, как установка полей "last_changed", должны отображаться в представлении, а не в сериализаторе.
Viewsets
В совершенно другом месте инфраструктура Django REST предоставляет Viewsets
. Это организованная коллекция представлений, вращающаяся вокруг реализации CRUD API для модели.
Таким образом, он структурирует его функциональность в виде набора методов, а именно create()
, retrieve()
/list()
, update()
и delete()
.
Основной момент: нет никакого соединения между методом viewet create()
и методом сериализатора create()
.
Просто случается, что реализация методов viewset по умолчанию использует ModelSerializer
и что реализация по умолчанию этого метода serializer save()
делегирует задание методам с тем же именем.
Кстати, пример last_changed
, вот как это сделать в представлении:
def perform_create(self, serializer):
now = timezone.now()
serializer.save(initial_creation=now, last_changed=now)
def perform_update(self, serializer):
serializer.save(last_changed=timezone.now())
Это функционально эквивалентно приведенному выше примеру, но живет в представлении.
Заключение
Итак, вернемся к вашему вопросу, конкретная вещь, которую вы должны переопределить, зависит от того, какой объект отвечает за задачу, которую вы хотите добавить.
- Если ваше пользовательское поведение является частью процесса сериализации, то есть процесс преобразования необработанных данных в правильную модель Django и ее сохранение, вы должны переопределить методы
Serializer
. - Если, с другой стороны, ваше пользовательское поведение специфично для вашего вида, тогда вы должны переопределить методы
Viewset
.
В качестве подсказки вы можете задать себе следующий вопрос: если я использую тот же сериализатор в другом месте (возможно, другой вид), должен ли он всегда отображать это поведение?