Getting Started with Celery and Django

February 4, 2012

We're going to implement a simple asynchronous task from a Django site, using Celery with a Redis back end. This task will send an email, based on parameters passed through the task to it. We assume you have an existing Django project and are adding celery to it.

Install software

We need to install redis

# apt-get install redis

Install Required Libraries

Use pip to install the following python libraries:

redis
django-celery-with-redis

Write Task

Here's the task code we're going to use.

from celery.task import task
from django.template.loader import render_to_string
from django.core.mail import EmailMessage
from django.conf import settings

@task(ignore_result=True)
def notify(pThing, pType, pUser):
    """
    Send an admin notification email when something happens
    """
    lDestination = ['address@destination.co.uk']
    lFrom = 'address@from.co.uk'
    lContext = { 'Thing' : pThing,
                 'User' : pUser,
               }

    lSubject = render_to_string('email/%s_subject.txt' % (pType), lContext)
    lSubject = "%s %s" % (settings.EMAIL_SUBJECT_PREFIX, lSubject) 
    lSubject = ''.join(lSubject.splitlines())          # Email subject *must not* contain newlines

    lMessage = render_to_string('email/%s.txt' % (pType), lContext)

    lEmailMessage = EmailMessage(subject=lSubject,
                            body=lMessage,
                            from_email=lFrom,
                            to=lDestination,
                            bcc=[])
    lEmailMessage.send(True)

This function has been saved into a file called notifications.py, and this is inside a package called drumcoder.tasks.

settings.py

We need the following inside settings.py:

BROKER_URL = "redis://localhost:6379/0"
CELERY_RESULT_BACKEND = "redis"
CELERY_REDIS_HOST = "localhost"
CELERY_REDIS_PORT = 6379
CELERY_REDIS_DB = 0
CELERY_IMPORTS = ("drumcoder.tasks.notifications", )
CELERY_SEND_TASK_ERROR_EMAILS = True
CELERYD_LOG_FILE='/tmp/celery.log'
import djcelery
djcelery.setup_loader()

Call Task

We now need to call the task from our code. We first need to import it, directly from where it is defined:

from drumcoder.tasks.notifications import notify

We then call it using a delay() function call, passing in parameters as if we were calling the function directly:

notify.delay(lContest, 'edit_contest', request.user)

Run Celery Daemon

Finally, we need to run the Celery Daemon. This can be done through manage.py:

$ ./manage.py celeryd

If you now run up the web app in a second command prompt with ./manage.py runserver, the task should now be run successfully when it is triggered.

Tags: django celery redis