🔖 Справочник — Урок 45

← К оглавлению урока

⚡ Шпаргалка по сигналам и email

# Импорты сигналов
from django.db.models.signals import post_save, pre_save, post_delete, pre_delete, m2m_changed
from django.dispatch import receiver

# Обработчик через декоратор
@receiver(post_save, sender=MyModel)
def handler(sender, instance, created, **kwargs): ...

# Обработчик через connect
signal.connect(handler, sender=MyModel)

# Email в settings.py (dev)
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

# Email в settings.py (prod)
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True

# Отправить письмо
from django.core.mail import send_mail
send_mail('Subject', 'Body', 'from@ex.com', ['to@ex.com'])

# Регистрация в apps.py
def ready(self):
    import myapp.signals

Встроенные сигналы Django

Сигнал Модуль Когда срабатывает Ключевой параметр
pre_save django.db.models.signals Перед вызовом Model.save() instance (ещё не сохранён в БД)
post_save django.db.models.signals После вызова Model.save() created (True/False)
pre_delete django.db.models.signals Перед Model.delete() instance (ещё есть в БД)
post_delete django.db.models.signals После Model.delete() instance (удалён, pk=None)
m2m_changed django.db.models.signals При изменении ManyToMany action, pk_set
pre_migrate django.db.models.signals Перед запуском миграций app_config
post_migrate django.db.models.signals После выполнения миграций app_config

Параметры сигналов post_save / pre_save

ПараметрТипОписание
senderclassКласс модели, отправляющий сигнал
instanceModel instanceЭкземпляр модели, который сохраняется
createdboolTrue — создан, False — обновлён (только post_save)
rawboolTrue при loaddata/fixtures (не вызывать логику!)
usingstrПсевдоним базы данных ('default')
update_fieldsfrozenset | NoneПоля, переданные в save(update_fields=[...])

Параметры m2m_changed (action)

Значение actionКогда
pre_addДо добавления объектов в ManyToMany
post_addПосле добавления объектов в ManyToMany
pre_removeДо удаления объектов из ManyToMany
post_removeПосле удаления объектов из ManyToMany
pre_clearДо очистки всех связей ManyToMany
post_clearПосле очистки всех связей ManyToMany

Регистрация обработчиков

СпособСинтаксисКогда использовать
Декоратор @receiver @receiver(post_save, sender=Model) Предпочтительный способ, читаемый и лаконичный
Метод .connect() post_save.connect(fn, sender=Model) Когда нужна динамическая/условная регистрация
Отключение post_save.disconnect(fn, sender=Model) В тестах для изоляции поведения

Настройки EMAIL в settings.py

ПараметрОписаниеПример
EMAIL_BACKENDБэкенд отправки'...console.EmailBackend'
EMAIL_HOSTSMTP-сервер'smtp.gmail.com'
EMAIL_PORTПорт SMTP587
EMAIL_USE_TLSВключить TLSTrue
EMAIL_USE_SSLВключить SSL (порт 465)False
EMAIL_HOST_USERЛогин SMTP'your@gmail.com'
EMAIL_HOST_PASSWORDПароль SMTPИз переменной окружения
DEFAULT_FROM_EMAILОтправитель по умолчанию'noreply@example.com'

Доступные EMAIL_BACKEND

БэкендОписание
django.core.mail.backends.console.EmailBackend Вывод в консоль — для разработки
django.core.mail.backends.smtp.EmailBackend Реальная отправка через SMTP — для продакшена
django.core.mail.backends.filebased.EmailBackend Сохранение в файл — для отладки без консоли
django.core.mail.backends.locmem.EmailBackend Хранение в памяти (django.core.mail.outbox) — для тестов
django.core.mail.backends.dummy.EmailBackend Ничего не делает — полная заглушка

Функция send_mail()

from django.core.mail import send_mail

send_mail(
    subject,          # str: тема письма
    message,          # str: текст письма (plain text)
    from_email,       # str | None: отправитель (None = DEFAULT_FROM_EMAIL)
    recipient_list,   # list[str]: список получателей
    fail_silently=False,    # bool: True — не бросать исключение
    auth_user=None,         # str: логин для SMTP (переопределяет EMAIL_HOST_USER)
    auth_password=None,     # str: пароль (переопределяет EMAIL_HOST_PASSWORD)
    connection=None,        # EmailBackend: уже открытое соединение
    html_message=None,      # str: HTML-версия письма
)
# Возвращает количество успешно отправленных сообщений (0 или 1)

Класс EmailMessage (расширенные возможности)

from django.core.mail import EmailMessage

email = EmailMessage(
    subject='Hello',
    body='Body of the email',
    from_email='from@example.com',
    to=['to@example.com'],
    cc=['cc@example.com'],
    bcc=['bcc@example.com'],
    reply_to=['reply@example.com'],
)
email.attach('file.pdf', open('file.pdf', 'rb').read(), 'application/pdf')
email.send()