Какие основные сигналы существуют в Django и для чего они используются?

Ответ

Сигналы в Django — это реализация паттерна 'Наблюдатель' (Observer), которая позволяет одним компонентам системы (отправителям) уведомлять другие (получатели) о произошедших событиях. Это помогает создавать слабосвязанные приложения.

Основные встроенные сигналы

1. Сигналы моделей (django.db.models.signals)

Наиболее часто используемая группа. Они срабатывают в ответ на действия с моделями в базе данных.

  • pre_save / post_save: Срабатывают до и после вызова метода save() модели.
  • pre_delete / post_delete: Срабатывают до и после вызова метода delete() модели.
  • m2m_changed: Срабатывает при изменении связи ManyToManyField.

2. Сигналы жизненного цикла запроса (django.core.signals)

Позволяют выполнять действия на разных этапах обработки HTTP-запроса.

  • request_started / request_finished: Срабатывают в начале и в конце обработки запроса.
  • got_request_exception: Срабатывает при возникновении исключения во время обработки запроса.

Практический пример: создание профиля пользователя

Классический пример использования сигнала post_save — автоматическое создание объекта Profile при регистрации нового пользователя (User).

from django.db.models.signals import post_save
from django.contrib.auth.models import User
from django.dispatch import receiver
from .models import Profile

# Декоратор @receiver связывает функцию-обработчик с сигналом
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    """
    Обработчик сигнала post_save для модели User.
    - sender: Класс модели, отправивший сигнал (User).
    - instance: Экземпляр модели, который был сохранен.
    - created: Флаг, равный True, если была создана новая запись в БД.
    """
    if created:
        Profile.objects.create(user=instance)

Этот код гарантирует, что у каждого нового пользователя будет связанный с ним профиль, при этом логика создания профиля отделена от логики создания пользователя.

Ответ 18+ 🔞

А, сигналы в Джанго! Ну это ж, блядь, классика, ёпта! Слушай, представь себе такую хуйню: есть у тебя в приложении куча компонентов, и они все друг про друга нихуя не знают, как соседи по лестничной клетке. И вот одному из них надо крикнуть: «Эй, народ, я тут только что пользователя создал!». А другому в это время похуй, он чай пьёт. Но если он подписался на этот крик — он услышит и сделает своё дело. Это и есть паттерн «Наблюдатель», только в питоньем, джанговском исполнении, блядь.

Основные встроенные сигналы, которые тебе в жизни пригодятся

1. Сигналы моделей (django.db.models.signals)

Эти, сука, самые важные. Они срабатывают, когда ты что-то делаешь с моделями в базе данных. Прямо как скрытые камеры в сортире, только полезные.

  • pre_save / post_save: Один орёт до того, как save() отработает, второй — после. Типа «щас буду сохраняться, народ!» и «я сохранился, пизда!».
  • pre_delete / post_delete: Та же хуйня, но с удалением. «Щас удалюсь!» и «Я удалился, прощайте, пидоры!».
  • m2m_changed: Этот, блядь, особый. Он орет, когда меняется связь «многие-ко-многим». Типа «ой, меня только что добавили в новую группу, ёба!».

2. Сигналы жизненного цикла запроса (django.core.signals)

Это уже про HTTP-запросы. Представь, что твой сервер — это ресторан, а эти сигналы — крики официантов: «гость пришёл!», «гость ушёл!», «гость блеванул в суп!».

  • request_started / request_finished: Начало и конец обработки запроса. Всё просто.
  • got_request_exception: А вот это, блядь, самый драматичный. Срабатывает, когда в процессе запроса случается пиздец (исключение). Кричит: «ВСЁ ПРОПАЛО, ШЕФ, У НАС КРАШ!».

Практический пример: создание профиля пользователя

Ну это, сука, must have для любого, кто делает регистрацию. Без этого — ты просто мудак, который заставляет пользователя создавать профиль вручную. Смотри, как это делают умные люди:

from django.db.models.signals import post_save
from django.contrib.auth.models import User
from django.dispatch import receiver
from .models import Profile

# Декоратор @receiver — это такая волшебная пизда, которая привязывает твою функцию к сигналу.
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    """
    Обработчик сигнала post_save для модели User.
    - sender: Класс модели, который орал (User).
    - instance: Конкретный экземпляр, который только что сохранили.
    - created: Флаг, который True, если запись новая (только что создали, а не обновили).
    - **kwargs: Всякая другая хуйня, которую сигнал может подкинуть.
    """
    if created:  # Если пользователя только что создали, а не просто обновили его email
        Profile.objects.create(user=instance)  # Бдыщ! Профиль создан. Магия, блядь!

Вот и вся магия. Пользователь зарегался — сигнал post_save орет — эта функция слышит — создаёт профиль. И всё это, блядь, слабосвязанно. Можешь потом хоть десять таких обработчиков навесить, и они не будут друг другу мешать. Красота, ёпта!