Сигналы в Django
Сигналы django могут стать полезными, когда мы пытаемся разработать некоторую функциональность, основанную на событиях, в нашем бэкэнде.
В django у нас есть два объекта, один из которых является отправителем, а другой - получателем, отправитель отправит сигнал о любом конкретном событии, и все получатели, которые прослушивают это событие, уведомляются сигналом и выполняют определенные действия.
Сигналы на основе моделей Django
Давайте рассмотрим несколько примеров с использованием встроенных сигналов django.
Определим несколько моделей в django models.py
from django.db import models
from django.contrib.auth.models import User
import datetime
# Create your models here.
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
profile_url = models.URLField()
mobile = models.CharField(max_length=20, default='999-999-9999')
funds = models.FloatField(default=2000)
def __str__(self):
return "[PROFILE]:" + self.user.username
class Log(models.Model):
timestamp = models.DateTimeField(default=datetime.datetime.now)
message = models.TextField()
def __str__(self):
return self.message
Здесь мы определили профиль двух моделей, который расширяет встроенную модель пользователя models.OneToOneField
, а другая - модель Log
, которая просто используется для хранения сообщений журнала в базе данных.
Теперь давайте определим reveiver, который использует сигнал post_save
, который срабатывает после сохранения конкретной модели в базе данных.
# .... models defined above
from django.db.models.signals import post_save
from django.dispatch import receiver
# triggred when User object is created
@receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(
user=instance
)
# triggred when User object is saved
@receiver(post_save, sender=User)
def log_user_saved(sender, instance, **kwargs):
Log.objects.create(
message=f"user {instance.username} is saved"
)
# triggred when Profile object is saved
@receiver(post_save, sender=Profile)
def log_profile_saved(sender, instance, **kwargs):
Log.objects.create(
message=f"profile {instance} is saved"
)
Как вы можете видеть выше, мы создали 3 функции приемника, давайте посмотрим на каждую из них.
create_profile
этот приемник срабатывает, когда генерируется сигнал post_save для модели пользователя, т. е. после того, как модель пользователя была сохранена в базе данных, модель пользователя генерирует сигнал post_save, и срабатывает приемник create_profile
в create_profile мы создаем профиль для пользователя, мы можем проверить это, перейдя к панели администратора django и создав пользователя
Создание пользователя
Пользователь изменен
Профиль создан
Как мы видим на изображении выше, профиль создается автоматически для пользователя с помощью сигнала post_save
Аналогично, если мы перейдем к модели журнала, мы увидим журналы, созданные для каждого сигнала.
на изображении выше мы видим, что объекты журнала создаются при срабатывании сигнала пользователя и профиля.
аналогично post_save у нас есть такие сигналы, как pre_save, pre_delete, post_delete, pre_init, post_init, m2m_changed
Приемник работает с различными сигналами
pre_init
receiver_function(sender, *args, **kwargs)
post_init
receiver_function(sender, instance)
pre_save
receiver_function(sender, instance, raw, using, update_fields)
post_save
receiver_function(sender, instance, created, raw, using, update_fields)
pre_delete
receiver_function(sender, instance, using)
post_delete
receiver_function(sender, instance, using)
m2m_changed
receiver_function(sender, instance, action, reverse, model, pk_set, using)