En la ultima versión de Celery (4.0) llego con varios cambios que rompen previos desarrollos (Era de esperar) realizados con celery 3.1 (Lanzado en 2013), por ende decidí realizar un nuevo tutorial utilizando Django 1.10 y Celery 4.1, explicando a su vez los cambios que rompen previos desarrollos.
Tutorial con la versión actualizada de Celery la cual incluye cambios mayores. Celery & Django
Celery es un framework para el manejo de tareas basado en colas, basándose en el patrón de diseño Productor consumidor donde el productor le envía trabajo a realizar al consumidor celery se encarga de manejarnos tanto el manejo de la cola de trabajos (jobs) como los workers (consumidores / trabajadores) que serán los que realicen dicha tarea. En este post estaremos integrando Django & Celery y algunos casos de usos para los que son buenos.
Podemos representar celery en el siguiente diagrama:
Donde podemos ver que Celery en quien encola el job y es quien maneja los workers para procesar dichos jobs.
Entre las características principales de Celery se encuentran:
- Poder ejecutar tareas de forma asíncronas.
- Ejecutar tareas de forma recurrente algo así como crontabs.
- Ejecutar tareas con una fecha en especifico.
Celery es uno de los frameworks mas importantes que he conocido en el entorno python, todo proyecto que quiera realizar una actividad en background lo primero que debe pensar es en Celery. Celery se integra bien con Django y es lo que veremos ahora.
h3>Instalación
Primero creamos nuestro proyecto Django
django-admin startproject app_mail
Luego creamos nuestro entorno dentro del proyecto Django y lo activamos
cd app_mail virtualenv env source env/bin/activate
Ahora instalamos los paquetes Celery y redis, desde la version 3.1 Django se integra perfectamente con Celery, por lo que no es necesario utilizar librerías como ‘Djcelery‘
pip install -U "Celery[redis]"
Ahora vamos a crear una aplicación simple para nuestro proyecto, la misma tendrá la funcionalidad de enviar un correo electrónico utilizando sendmail de Linux.
django-admin startapp celery_example
Luego tendremos que agregar nuestra aplicación ya creada a nuestras INSTALLED_APPS
Una vez instaladas vamos a generar y correr las migraciones.
python manage.py makemigrations python manage.py migrate
Como estamos creando un proyecto simple la base de datos que este proyecto tendrá sera sqlite.
Creamos una vista simple que solo imprima un texto para fines de prueba y ejecución de Celery.
#celery_example/views.py from django.shortcuts import render, HttpResponse # Create your views here. def index(request): return HttpResponse("Hola")
Y agregamos esa vista a nuestro archivo de url.py
#app_mail/urls.py from django.conf.urls import url from django.contrib import admin from celery_example.views import index urlpatterns = [ url(r'^$', index), url(r'^admin/', admin.site.urls), ]
Corremos nuestra aplicación
python manage.py runserver
Y tendremos nuestro «Hola» mostrado en pantalla.
Configurar Celery
Para configurar nuestro proyecto Django junto a Celery tenemos que crear un archivo llamado celery.py donde colocaremos la creación de nuestra aplicación celery y demás configuraciones.
from __future__ import absolute_import, unicode_literals import os from celery import Celery # set the default Django settings module for the 'celery' program. os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'app_mail.settings') app = Celery('proj') #Nota 1 app.config_from_object('django.conf:settings', namespace='CELERY') #Nota 2 app.autodiscover_tasks() #Nota 3 app.conf.update( BROKER_URL = 'redis://localhost:6379/0', #Nota 4 )
Bueno eso que vimos ahí arriba seria nuestra aplicación Celery, detallares los puntos importantes de el código colocado ahi arriba.
#Nota 1 Creamos nuestra aplicación celery y le pasamos un nombre
#Nota 2 Inicializamos nuestra app celery con la configuración de nuestro proyecto Django
#Nota 3 Como su nombre lo dice gracias a esta linea Celery auto-inspeccionara nuestras app y buscara métodos con la anotación ‘@tasks’ de celery.
#Nota 4 Colocamos el broker que estaremos utilizados para guardar los jobs, en esta nueva versión de Celery no se puede utilizar Django y Beanstalk por falta de fondos para dicho soporte.
Ahora procederemos a en nuestra aplicación Django llamada ‘celery_example’ crearemos un archivo llamado ‘tasks.py’ donde colocaremos nuestras tareas a ejecutar.
#celery_example/tasks.py from app_mail.celery import app @app.task def prueba_suma(x, y): return x + y @app.task def prueba_resta(x, y): return x - y
Una vez creadas nuestras majestuosas tareas, podemos proceder a correr nuestro proyecto Django y nuestra app celery (Son 2 procesos aparte).
En una terminal (Django app)
python manage.py runserver 8080
En otra terminal
celery worker -A app_mail.celery --loglevel=info
Es bueno correr la aplicación con el log level info así podremos ver las tareas que estas disponibles para ser ejecutadas en los workers de celery. Si todo se realizo bien en output de nuestra app celery seria algo como esto:
Para llamar una de estas tareas desde nuestro proyecto Django solo tenemos que importar los métodos de nuestro archivo ‘tasks.py‘ y ejecutarlos (Si, así de facil). Como solo tenemos una vista simple y de prueba ejecutamos la llamada ahí.
from django.shortcuts import render, HttpResponse from tasks import prueba_suma # Create your views here. def index(request): resultado = prueba_suma(5, 6) return HttpResponse("Hola")
Si ejecutamos nuestro método de esa forma se ejecutar en el foreground (Mientras el request este vivo) y no es lo que queremos para que se ejecute en los procesos de celery tendremos que hacerlo un poco diferente.
from django.shortcuts import render, HttpResponse from tasks import prueba_suma # Create your views here. def index(request): resultado = prueba_suma.delay(5, 6) return HttpResponse("Hola")
De esta forma podremos ejecutarla en el background y podremos ver que en el output de celery tendremos algo como esto:
Donde nos muestra cuando la tarea entro a la cola de trabajo y cuando se ejecuto.
Ahora vamos a crear una tarea que nos permita enviar una correo, por que un correo bueno es un muy buen ejemplo de cosas que tenemos que hacer de forma asíncrona, nuestro usuarios no pueden estar esperando en el hilo principal de la aplicación a que enviemos un correo.
Tendremos que configurar los datos SMTP de nuestra aplicación Django
#settings.py EMAIL_BACKEND='django.core.mail.backends.smtp.EmailBackend' EMAIL_HOST = "" SERVER_EMAIL = "" EMAIL_HOST_USER = "" EMAIL_HOST_PASSWORD = ""
Y luego nuestra tarea para enviar correos:
from django.core.mail import send_mail @app.task def enviar_mail(asunto, contenido, destinatario): send_mail(asunto, contenido, '[email protected]', [destinatario], fail_silently=False)
Para ejecutar dicha llamada solo tenemos que importarla y ejecutarla con delay para que se ejecute en los procesos de celery.
from tasks import enviar_mail enviar_mail.delay("Asunto", "Contenido mensaje", "[email protected]")
Y hasta aquí este tutorial, espero que al igual que me sirvió a mi conocer esta herramienta le pueda servir a alguien mas y compartir el conocimiento.
Aqui coloco el código del ejemplo completo Github