I am learning Celery. In my website, I let people register an account. Once they create a new account, it will automatically send an activation email to their user email address.
Everything works well but now I want to use Celery to send the email asynchronously.
I use RabbitMQ as broker, version 3.1.5 and Celery 3.1.7 (the latest version), as they say this version does not need djcelery. So all I need is just to install Celery.
I followed the instruction as celery its website, Configurate my django.
proj
--proj/celery.py
Here is my celery.py:
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', 'proj.settings')
app = Celery('proj')
# 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))
And this is the tasks.py that I put in my app folder:
proj
---proj/celery.py
---app/tasks.py
tasks.py
from __future__ import absolute_import
from celery.decorators import task
@task()
def user_send_activation_email(user):
user.send_activation_email()
I added the send_activation_email
function to user models, so user can send the email.
This is my views.py:
from django.shortcuts import render_to_response, redirect,render
from django.conf import settings
from django.http import HttpResponse,HttpResponseRedirect,Http404
from django.template import RequestContext
from app.accounts.forms import SignupForm
from django.contrib.auth import get_user_model
from app.sns_utils import generate_sha1
from app.tasks import user_send_activation_email
def signup(request):
if request.method=='POST':
form=SignupForm(data=request.POST)
if form.is_valid():
UserModel=get_user_model()
username = form.cleaned_data['username']
email = form.cleaned_data['email']
password = form.cleaned_data['password']
user=UserModel.objects.create_user(username=username,email=email,password=password)
user.activation_key = generate_sha1(username)
user.save()
user_send_activation_email.delay(user=user)
return redirect('/')
And here is how I configured Celery in settings.py:
BROKER_URL = 'amqp://guest:guest@localhost:5672//'
CELERY_RESULT_BACKEND = 'amqp://guest:guest@localhost:5672//'
CELERY_TASK_SERIALIZER = 'json'
everything just follow celery its website say.
Once I manage.py runserver
, in the signup page, I register a new account with username vmuser630
, and it shows this error:
EncodeError at /accounts/signup/
<MyUser: vmuser630> is not JSON serializable
Request Method: POST
Request URL: http://localhost:8000/accounts/signup/
Django Version: 1.6
Exception Type: EncodeError
Exception Value:
<MyUser: vmuser630> is not JSON serializable
Exception Location: C:\Python33\lib\json\encoder.py in default, line 173
Python Executable: C:\Python33\python.exe
Python Version: 3.3.2
If I remove this from settings.py:
CELERY_TASK_SERIALIZER = 'json'
and try again manage.py runserver
, I'm just redirected to the '/' page. The new account is in the database, but I did not get the activation email.
It looks like the send email task has just been passed, nothing happened.
When i change the send email function back to:
user.send_activation_email()
it means I do not user celery, it works, I can get the activation email.
Why does it show the error not JSON serializable?
Celery need to serialize the arguments for a task. Here, user
is not serializable, but you can replace it with its ID:
In tasks.py:
from __future__ import absolute_import
from celery.decorators import task
from django.contrib.auth import get_user_model
@task()
def user_send_activation_email(user_id):
user = get_user_model().objects.get(pk=user_id)
user.send_activation_email()
Then call it from views.py using:
user_send_activation_email.delay(user_id=user.pk)
see setting-task_serializer, you can set CELERY_TASK_SERIALIZER = 'pickle' in celery conf.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With