⚡ Шпаргалка по сигналам и 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
| Параметр | Тип | Описание |
sender | class | Класс модели, отправляющий сигнал |
instance | Model instance | Экземпляр модели, который сохраняется |
created | bool | True — создан, False — обновлён (только post_save) |
raw | bool | True при loaddata/fixtures (не вызывать логику!) |
using | str | Псевдоним базы данных ('default') |
update_fields | frozenset | 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_HOST | SMTP-сервер | 'smtp.gmail.com' |
EMAIL_PORT | Порт SMTP | 587 |
EMAIL_USE_TLS | Включить TLS | True |
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()