Signals¶
Signals on database is a native Django signals.
Available variables for rules on Signals:
{{ date }} - current date
{{ date_time }} - current datetime
{{ site }} - current site
{{ domain }} - current site domain
{{ old_instance }} - old instance for pre_save
{{ current_instance }} - available when Update model state is enabled
{{ instance }} - instance from received signal
{{ ... }} - all instance fields as vars
When all signals was configured, you need to reload your wsgi application. Auto-reloading can be configured on settings by WSGI_AUTO_RELOAD/UWSGI_AUTO_RELOAD. But if you launch application on several instances, do it manually.
Note: Don’t use a big intervals, if deferred tasks on queue more than 3-4k. It can crash a celery worker.
For deferred tasks best way is a crontab command + database queue.
You can add DB_MAILER_SIGNAL_DEFERRED_DISPATCHER = 'database'
into project settings,
and call crontab command send_dbmail_deferred_signal
.
Sending signals¶
from dbmail.exceptions import StopSendingException
from dbmail.signals import pre_send, post_send
from dbmail.backends.sms import Sender as SmsSender
def check_balance(*args, **kwargs):
# "if" condition is unnecessary due to the way we connect signal to handler
if kwargs['instance']._backend.endswith('sms'):
balance = ...
if balance == 0:
raise StopSendingException
def decrease_balance(*args, **kwargs):
# decrease user balance
pass
pre_send.connect(check_balance, sender=SmsSender)
post_send.connect(decrease_balance, sender=SmsSender)
When you want transmit some **kwargs to signal, you can use signals_kwargs.
from dbmail import send_db_mail
send_db_mail(
'welcome', 'user@example.com',
signals_kwargs={'user': User.objects.get(pk=1)}, use_celery=False
)
When using MailSubscriptionAbstract model, you may want to check instance for uniqueness before creating it. In this case you should use either model meta option “unique-together” or use pre-save signal, that raises IntegrityError in case of duplicates.
from django.db import models
def check_address_is_unique(sender, instance, **kwargs):
if not (instance.is_checked and instance.is_enabled):
return
query = sender.objects.filter(
is_checked=True,
is_enabled=True,
address=instance.address,
backend=instance.backend
)
if instance.pk:
query = query.exclude(pk=instance.pk)
if query.exists():
raise IntegrityError('address must be unique')
models.signals.pre_save.connect(
check_address_is_unique, sender=MailSubscription)