Sending Email using celery in Django

What is celery?

Celery is an asynchronous task queue/job queue based on distributed message passing. It is focused on real-time operation but supports scheduling as well. For this post, we will learn how to send emails using celery.

An important use of celery

  • You never want end users to have to wait unnecessarily for pages to load or actions to complete. If a long process is part of your application’s workflow, you can use Celery to execute that process in the background, as resources become available, so that your application can continue to respond to client requests. This keeps the task out of the application’s context.

Setup

Before diving into celery create a brand new Django project with basic configurations, then fire up the server and navigate to http://127.0.0.1:8000/ in your browser.

Next, let’s install celery using pip

Shell command
pip install celery
pip freeze > requirements.txt

Now to integrate celery we need to follow three steps.

Step 1: Add celery.py to your project’s root folder(Where the settings.py file is present)

#celery.py(add the exact code, just change your project name)
from __future__ import absolute_import
import os
from celery import Celery
from django.conf import settings
# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'your_project_name.settings')
app = Celery('your_project_name')
# Using a string here means the worker will not have to
# pickle the object when using Windows.
app.config_from_object('django.conf:settings')
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
@app.task(bind=True)
def debug_task(self):
    print('Request: {0!r}'.format(self.request))

Step 2: Import your Celery app

To ensure that the Celery app is loaded when Django starts, add the following code into the __init__.py file that sits next to your settings.py file:

from __future__ import absolute_import
# This will make sure the app is always imported when
# Django starts so that shared_task will use this app.
from .celery import app as celery_app

Your project layout should look like something this

├── manage.py
├── your_project
│   ├── __init__.py
│   ├── celery.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── requirements.txt

Step 3: Install Redis as a “Broker”

Celery uses “brokers” to pass messages between a Django Project and the Celery workers. In this tutorial, we will use Redis(you can also use RabbitMQ) as the message broker.

First, install Redis from the official download page or via brew (brew install redis) and then turn to your terminal, fire up the server:

#shell
redis-server

To test if Redis is working or not

#shell
$ redis-cli ping

Redis should reply with PONG try-it

Once Redis is working, add the following code to your settings.py file

# CELERY STUFF
BROKER_URL = 'redis://localhost:6379'
CELERY_RESULT_BACKEND = 'redis://localhost:6379'
CELERY_ACCEPT_CONTENT = ['application/json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TIMEZONE = 'Asia/kolkata'

You also need to add Redis as a dependency in the Django Project:

#shell
$ pip install redis
$ pip freeze > requirements.txt

That’s it! You should now be able to use Celery with Django.

Before moving on, let’s run a few sanity checks to ensure all is well…

Test that the Celery worker is ready to receive tasks:

#shell
$ celery -A your_django_project worker -l info
...
[2015-07-07 14:07:07,398: INFO/MainProcess] Connected to redis://localhost:6379//
[2015-07-07 14:07:07,410: INFO/MainProcess] mingle: searching for neighbors
[2015-07-07 14:07:08,419: INFO/MainProcess] mingle: all alone

Kill the process with CTRL-C. Now, test that the Celery task scheduler is ready for action:

$ celery -A your_django_project beat -l info
...
[2015-07-07 14:08:23,054: INFO/MainProcess] beat: Starting...

Boom!

Again, kill the process when done.

Celery Tasks

Celery uses tasks, which can be thought of as regular Python functions that are called with Celery.

Now let’s create a simple task to send mail using celery.

First, create a tasks.py file inside your apps folder

#your_app/tasks.py
from celery.decorators import task
from celery.utils.log import get_task_logger
from django.core.mail import EmailMessage
from time import sleep
logger = get_task_logger(__name__)
@task(name='send_email_task')
def send_mail_task(subject, message, email_from, recepient_list):
    msg = EmailMessage(subject, message, email_from, recepient_list)
    msg.content_subtype = 'html'
    msg.send()

Then you can run this task asynchronously with Celery like so:

#inside your views.py or anywhere you want
#import tasks.py and call the function
send_mail_task.delay(your_subject, your_messaage, your_email, your_recepient_list)

That’s it you are good to go

Cheers!!

Happy Coding!


Buy Django book for advance learning

This Post Has 2 Comments

Leave a Reply