Когда создаются и обновляются вызовы в djangorestframework serializer?

В настоящее время я реализую djangorestframework для моего API RESTful. Поиграв с ним, я до сих пор не понимаю, для чего используются .create(self, validated_data) и .update(self, validated_data) в сериализаторе. Как я понимаю, CRUD вызывает только 4 основных метода в viewsets.ModelViewSet: create(), retrive(), update() и destroy().

Я также попытался отладить и распечатать материал, чтобы увидеть, когда методы .create() и .update() вызываются как в ModelViewSet, так и в ModelSerializer. По-видимому, только методы из ModelViewSet вызываются, когда я выполняю HTTP-глаголы. Однако для ModelSerializer я не вижу никаких вызовов в этих двух методах. Я просто хочу знать, какие методы используются в ModelSerializer, так как я вижу, что люди много переопределяют эти методы в сериализаторе.

P/S: Я новичок в djangorestframework + извините за свой английский, так как я не родной.

Спасибо:)

Ответы

Ответ 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.

В качестве подсказки вы можете задать себе следующий вопрос: если я использую тот же сериализатор в другом месте (возможно, другой вид), должен ли он всегда отображать это поведение?

Ответ 2

Наконец, я понимаю, как .create() и .update() работают в Serializer (особенно ModelSerializer) и как они связаны с Viewsets (особенно ModelViewSet). Я просто хочу более четко разъяснить концепцию, если кто-то приходит к этому вопросу.

В принципе, 4 метода CRUD в ModelViewSet: .create(), .retrieve(), .update() и .destroy() будут обрабатывать вызовы из HTTP-глаголов. По умолчанию .create() и .update() из ModelViewSet вызывают .create() и .update() из ModelSerializer, вызывая метод .save() из класса BaseSerializer.

Затем метод save() определит, будет ли он вызывать .create() или .update() в ModelSerializer, определяя, существует или нет объект self.instance.

Ответ 3

В проекте rest-api создание, чтение, обновление и удаление является стандартом. В создании и обновлении нет большой разницы.

Обратитесь к this и

см. create() метод создаст элемент.

и

update() метод должен указать, какой элемент нужно обновить.