Making Django's Signals Async with Celery - a1k89/Blog GitHub Wiki
Prepare
- Django project with long-task logic (for example, push notifications to mobile clients)
- Celery with any backends
Problems
- Django signals synchronous by default
- We must to wait when transaction completed
- Clients can to wait response for a long time
Short description
- Configure celery
- Create application (for example,
notifier) - Configure
post_savesignal throughcelerytask - Configure
AppConfigto load function
Detail
- Create
notifierapplications - Add
tasks.py
tasks.py
import uuid
from collections import namedtuple
from django.db.models.signals import post_save
from run_celery import app
from some_apps.models import SomeModel1, SomeModel2, SomeModel3
Ctx = namedtuple('Ctx', 'class_name identifier')
models = [
SomeModel1,
SomeModel2,
SomeModel3
]
def register_models():
for model in models:
post_save.connect(_post_save,
sender=model,
dispatch_uid=uuid.uuid4())
def _post_save(sender, instance, **kwargs):
ctx = Ctx(class_name=instance.__class__.__name__,
identifier=instance.pk)
_async_post_save_handler.delay(ctx)
@app.task
def _async_post_save_handler(ctx: Ctx):
"""
Get model and instance from notifier object and then make
some other logic
"""
...
- Add to
apps.py:
notifier/apps.py`
from django.apps import AppConfig
class NotifierConfig(AppConfig):
name = 'notifier'
def ready(self):
from apps.notifier.tasks import register_models
register_models() # here!
Save and run Django and run celery.
Conclusion
celeryhelp you create async handlers to your Django models- Solution is great to separate
post_saveand async logic
Thanks for reading