Esto va dirigido a todas aquellas personas que ya tengan un proyecto de python con django en heroku activo, se obviara los pasos a seguir para subir un proyecto.

Requisitos previos
Primero que todo necesitaremos tener instalado en el proyecto celery y django-celery asi que vamos a ello:

  1. Instalar celery y django-celery en tu virtualenv:
    “pip install Celery django-celery”

Nota: recuerda cada nueva dependencia instalada debe ser agregada en el archivo requirements.txt para cuando se realice un push a heroku el instale esas dependencia. Puedes ver todas las dependencias instaladas ejecutando el comando pip freeze

 2. Después que se instalen todas las dependencias, en tu setting.py debemos agregar:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.sites',
    'djcelery'
]

ademas de importar

import djcelery
djcelery.setup_loader()

luego de realizar esta configuración ejecutamos el comando:
“python manage.py migrate djcelery”
para crear las tablas necesarias para configurar vía admin de django. si deseas ampliar mas puedes visitar los siguientes link https://github.com/celery/django-celery y http://www.celeryproject.org/

Nota: Para poder realizar pruebas locales en tu proyecto en necesario tener instalado un manejador para la cola de mensajes entre django y celery los cuales pueden ser Redis  https://redis.io/downloado Rabbitmq https://www.rabbitmq.com/download.html

  • Si decides utilizar redis debes instalar una dependencia en tu virtualenv pip install -U “celery[redis]” así como también agregarla al archivo requirements.txt. Después agregar en el archivo sentting.py: CELERY_BROKER_URL = ‘redis://localhost:6379/0’
  • Si deseas utilizar rabbitmq agrega en el archivo setting.py: CELERY_BROKER_URL = ‘amqp://localhost’

Recuerda para que funcione debe estar encendido el redis o el rabbitmq por la consola.

Configuración del celery
Tenemos que crear un nuevo archivo cuyo nombre sera celery.py en la carpeta te configuración de tu proyecto

  • Navega hasta el módulo de configuración del proyecto raíz (donde están los ajustes y los módulos de URL):
    yourproject
    -app
    -migrations
    __init__.py
    0001_initial.py
    admin.py
    app.ys
    models.py
                     tasks.py
    tests.py
    view.py
    -yourproject
                     __init__.py
                     celery.py
    setting.py
    urls.py
    wsgi.py
  • Dentro del archivo escribiras lo siguiente:
    from __future__ import absolute_import, unicode_literals
    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', 'yourproject.settings')
    app = Celery('yourproject')
    # Using a string here means the worker don't have to serialize
    # the configuration object to child processes.
    # - namespace='CELERY' means all celery-related configuration keys
    # should have a `CELERY_` prefix.
    app.config_from_object('django.conf:settings')
    
    # Load task modules from all registered Django app configs.
    app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
  • Luego actualizar el archivo __init__.py de la carpeta de configuración de tu proyecto:
    from __future__ import absolute_import, unicode_literals
    	
    	# 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
    
    	__all__ = ['celery_app']

con esto ya tendremos el celery correctamente configurado en tu proyecto. ahora procedamos a realizar las tareas en el proyecto

Realizando tareas asíncronas y peridódicas

  • Necesitas crear un archivo tasks.py en la aplicación Django que deseas(recuerda que debe ser una aplicación validad en INSTALLED_APPS):
    from __future__ import absolute_import, unicode_literals
    from celery import shared_task
    from account import models as account_models
    
    
    @shared_task
    def disableCodeRecoveryPassword(instance):
        instance = account_models.User.objects.get(id=instance)
        instance.recovery = ''
        instance.save()
        return True
  • Para terminar activaremos el worker con el siguente comando:“celery -A yourproject worker -l info”. pero antes teniendo tu servidor corriendo en otra terminal quedando asi:

Ahora que ya tenemos todos las configuraciones necesarias para iniciar una tarea asíncrona en django te mostrare como correrlo en heroku

Proyecto en heroku

Nota: Para poder utilizar celery en heroku debemos tener una cuenta premium porque cuando intentemos instalar el addons de redis o rabbitmq nos solicitara una tarjeta de credito

  • En el archivo Profile debemos agregar dos nuevas lineas quedado asi:
    web: gunicorn yourproject.wsgi --log-file -
    worker: python manage.py celery worker --without-gossip --without-mingle --loglevel=info
    beat: python manage.py celery beat –loglevel=info
  • luego debemos editar el archivo setting.py:
    BROKER_URL = os.environ.get("CLOUDAMQP_URL", "django://")
    
    BROKER_POOL_LIMIT = 1
    BROKER_CONNECTION_MAX_RETRIES = None
    BROKER_HEARTBEAT = None 
    RESULT_BACKEND = None EVENT_QUEUE_EXPIRES = 60 
    WORKER_PREFETCH_MULTIPLIER = 1 
    WORKER_CONCURRENCY = 50 
    CELERYBEAT_SCHEDULER ='djcelery.schedulers.DatabaseScheduler'

Antes de subir los cambios a heroku debemos agregar un nuevo addons en este ejemplo utilizaremos el addons de cloudAMQP escribiendo el siguente comando en la consola
“$ heroku addons:add cloudamqp
o puedes ir a heroku en la parte de resource y buscar el addons e instalarlo:

nota: la configuración previa solo funcionara con cloudamqp te invito a realizar tus pruebas con redis instalando el addons https://elements.heroku.com/addons/rediscloud

Luego de tener todo listo subimos el proyecto a heroku con esta nueva configuración, ahora para activar el worker en heroku debemos ejecutar el comando “$ heroku ps:scale worker=1”

si necesitas activar el beat puedes hacerlo mediante el mismo comando, solo cambiando el worker por beat “$ heroku ps:scale beat=1”

para simplificar las cosas puedes activar ambos a la vez: 
“$ heroku ps:scale worker=1 beat=1”

solo en el caso que estes utilizando tareas asíncronas y periódicas a la vez

Al hacerlo te se mostrara esto por la consola
“heroku-cli: update available from 6.14.36-15f8a25 to 6.15.25-635e5c6
Scaling dynos… done, now running beat at 1:Hobby, worker at 1:Hobby”
para todos los casos si solo activas el worker saldra: worker at 1:Hobby

para apagar los worker ejecute el comando
$ heroku ps:scale worker=0 beat=0

Para verificar que el worker esta funcionando bien ejecute el comando “heroku ps” 

finalmente visualice los logs de heroku ejecutando los comandos
heroku logs -t -p worker


heroku logs -t -p beat


para ver si no hay algún posible error o se realizo correctamente

para terminar ejecutar el comando
“heroku restart”

Si seguiste todos los pasos al pie de la letra podras realizar dejar tareas asincronas en heroku
Espero que haya sido útil esta guiá, comparte y deja tus comentarios :)!