Django Rest Framework вызывает пользовательскую функцию при создании модели

Предположим, я хочу делать некоторые дополнительные действия всякий раз, когда создается модель в моем Django App:

models.py:

class MyModel(models.Model):
  name = models.CharField(max_length=255)

  def do_some_extra_stuff(self):
    // whatever...
    return "I did some extra stuff"

Предположим, что дополнительный материал - это какая-то долго выполняющаяся асинхронная задача.

Я использую Django Rest Framework и имею стандартные ModelSerializer и ViewSet.

Мой вопрос в том, где лучше всего разместить вызов do_some_extra_stuff? Я могу предложить следующие варианты:

  1. В методе serializer.create
  2. В методе viewset.create
  3. В методе model.save
  4. В сигнале post_save

Я склоняюсь к #1 или #2, потому что я хочу, чтобы этот fn вызывался только при взаимодействии обычных пользователей с API - не при использовании Django Admin или shell.

Этот вопрос, вероятно, будет закрыт, потому что он основан на мнении, поэтому вот мое мнение по этому поводу!

Фоновые задачи

Используйте Celery или Django-RQ.

Celery "лучше", но Django-RQ (и самого RQ) почти всегда достаточно, если у вас есть хорошее логирование и отчет об ошибках. Обычно мы имеем дело не с переводами банковских счетов.

#2 - Viewset Based

Я считаю, что сериализаторы должны только сериализовать и проверять. Из-за этого любая пользовательская логика сохранения должна идти в ViewSet - впереди, видна в момент использования, и имеет доступ ко всему без всяких ухищрений контекста сериализатора.

class MyViewSet(ModelViewSet):

    def perform_create(self, serializer):
        # pass a value into save(), which passes it to model.create()
        serializer.save(org_id=self.request.user.secret_org_id)

        # use the serializer instance that was created to enqueue a bg task
        my_background_task.delay(item_pk=serializer.instance.pk)

Это просто предпочтение. Совершенно нормально поместить его в сериализатор, если так вы обычно выполняете другие задачи. Единственная цель - последовательность.

Это может иметь больше смысла, если вы представите себе использование 1 сериализатора для каждого действия - list, create и update.

Другие методы

#3 В методе model.save

model.save() не вызывается в некоторых редких случаях, и это не то место, где я ожидаю увидеть логику, запускающую другие задачи. Там работают некоторые очистители полей модели. Опять же, это предпочтение, но использование этого метода с DRF кажется необычным, в отличие от использования чистого django и использования админки сайта.

#4 В сигнале post_save

Мне кажется, что сигналы после сохранения находятся слишком далеко от модели, а также не вызываются в некоторых редких случаях (в основном, как и в #3). Я бы предпочел быть явным в таких вещах, поэтому я держу их близко к тому месту, где я ожидаю их увидеть. Мы используем сигналы post_save для других вещей, но они страдают от невозможности увидеть контекст, и в них трудно передать дополнительные параметры.

Вернуться на верх