Ответ
post_save — это сигнал в фреймворке Django, который отправляется сразу после того, как метод save() модели успешно завершил свою работу и данные были сохранены в базу данных. Это часть встроенной системы сигналов, позволяющей выполнять определенные действия в ответ на события, происходящие в приложении.
Использование сигналов, таких как post_save, позволяет отделить логику, не связанную напрямую с сохранением модели, и реализовать принцип слабой связанности (low coupling) компонентов системы.
Принцип работы:
Вы создаете функцию-обработчик (receiver), которая будет вызываться каждый раз, когда сигнал post_save срабатывает для указанной модели (sender).
Основной пример:
Предположим, мы хотим автоматически создавать профиль пользователя (UserProfile) каждый раз, когда создается новый пользователь (User).
# myapp/signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.auth.models import User
from .models import UserProfile
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
"""Обработчик сигнала для создания профиля."""
if created:
# Аргумент 'created' равен True только при первом сохранении
UserProfile.objects.create(user=instance)
# myapp/apps.py
from django.apps import AppConfig
class MyappConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'myapp'
def ready(self):
import myapp.signals # Важно импортировать сигналы здесь
Ключевые аргументы обработчика:
sender: Класс модели, который отправил сигнал (в примере —User).instance: Конкретный экземпляр модели, который был сохранен.created: Булево значение.True, если в базе данных была создана новая запись (эквивалентноINSERT).False, если запись была обновлена (UPDATE).
Частые сценарии использования:
- Создание связанных объектов (как в примере выше).
- Денормализация данных или обновление агрегированных значений.
- Инвалидация кэша при изменении данных.
- Отправка уведомлений (например, по email) после создания или обновления объекта.
Ответ 18+ 🔞
Ну, слушай, смотри, вот есть у тебя в Джанго эта штука — post_save. Это как такой сигнальчик, понимаешь? Ты модель сохранил в базу, всё, save() отработал, и тут — бац! — в эфир летит этот самый сигнал. А ты где-то в другом углу приложения можешь его поймать и сделать какую-нибудь свою, ебать, магию. Красота же, да? Разделил логику, не городи всё в один метод, принципы всякие соблюдаешь.
Как это, блядь, работает:
Представь, ты — диджей на радиостанции. Ты (post_save) объявляешь в эфир: "Так, народ, только что сохранился объект модели User!". А где-то в другом конце города у тебя сидит радиолюбитель с приёмничком. Это твой обработчик, receiver. Он эту хуйню ловит и начинает что-то своё делать.
Вот тебе классика жанра, на пальцах:
Допустим, у тебя есть юзер, и на каждого юзера надо автоматом создать профиль. Без этого сигнала пришлось бы везде, где создаёшь юзера, руками ещё и профиль лепить. Заебешься, блядь. А так — один раз написал и забыл.
# myapp/signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.auth.models import User
from .models import UserProfile
@receiver(post_save, sender=User) # Вешаем наш приёмничек на волну 'post_save' от модели User
def create_user_profile(sender, instance, created, **kwargs):
"""Функция, которая сработает, когда юзера сохранят."""
if created: # Вот это ключевой момент, ёпта! True — значит юзера только что СОЗДАЛИ, а не обновили.
UserProfile.objects.create(user=instance) # Бдыщ! Профиль готов.
# myapp/apps.py
from django.apps import AppConfig
class MyappConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'myapp'
def ready(self):
import myapp.signals # СУКА, ВАЖНО! Сигналы надо импортировать тут, иначе они не загрузятся!
Аргументы, которые тебе кидают в обработчик (приёмник):
sender: Это кто кричал в эфир. Класс модели, в нашем случае —User.instance: А это сам конкретный чувак, которого только что сохранили. Объект модели, живой, с его полями и данными.created: Флаг, просто пиздец какой важный.True— запись новая, только что в базу вставили.False— значит старую запись просто обновили. Без него можно наобновлять столько хуйни...
Где это, блядь, пригождается, кроме профилей?
Да везде, где надо что-то сделать ПОСЛЕ сохранения, но не в лоб, в том же методе.
- Создать кучу связанных объектов разом.
- Посчитать какие-то суммарные поля в другой модели (денормализация, ёпта).
- Сбросить кэш, потому что данные изменились, а кэш ещё старый.
- Отправить письмо или уведомление, что, мол, "ваш заказ №666 создан, идите нахуй".