Django-RQ
Django integration with RQ, a Redis based Python queuing library. Django-RQ is a simple app that allows you to configure your queues in Django's settings.py and easily use them in your project.
Support Django-RQ
If you find django-rq useful, please consider supporting its development via Tidelift.
Requirements
Installation
- Install
django-rq(or download from PyPI):
pip install django-rq
- Add
django_rqtoINSTALLED_APPSinsettings.py:
INSTALLED_APPS = (
# other apps
"django_rq",
)
- Configure your queues in Django's
settings.py:
RQ_QUEUES = {
'default': {
'HOST': 'localhost',
'PORT': 6379,
'DB': 0,
'USERNAME': 'some-user',
'PASSWORD': 'some-password',
'DEFAULT_TIMEOUT': 360,
'DEFAULT_RESULT_TTL': 800,
'REDIS_CLIENT_KWARGS': { # Eventual additional Redis connection arguments
'ssl_cert_reqs': None,
},
},
'with-sentinel': {
'SENTINELS': [('localhost', 26736), ('localhost', 26737)],
'MASTER_NAME': 'redismaster',
'DB': 0,
# Redis username/password
'USERNAME': 'redis-user',
'PASSWORD': 'secret',
'SOCKET_TIMEOUT': 0.3,
'CONNECTION_KWARGS': { # Eventual additional Redis connection arguments
'ssl': True
},
'SENTINEL_KWARGS': { # Eventual Sentinel connection arguments
# If Sentinel also has auth, username/password can be passed here
'username': 'sentinel-user',
'password': 'secret',
},
},
'high': {
'URL': os.getenv('REDISTOGO_URL', 'redis://localhost:6379/0'), # If you're on Heroku
'DEFAULT_TIMEOUT': 500,
},
'low': {
'HOST': 'localhost',
'PORT': 6379,
'DB': 0,
}
}
RQ_EXCEPTION_HANDLERS = ['path.to.my.handler'] # If you need custom exception handlers
Admin Integration
New in Version 4.0
Django-RQ automatically integrates with Django's admin interface. Once installed, navigate to /admin/django_rq/dashboard/ to access:
- Queue statistics and monitoring dashboard
- Job registry browsers (scheduled, started, finished, failed, deferred)
- Worker management
- Prometheus metrics endpoint (if
prometheus_clientis installed)
The views are automatically registered in Django admin and a link to the dashboard is added to the admin interface's sidebar. If you want to disable this link, add RQ_SHOW_ADMIN_LINK = False in settings.py.
Standalone URLs (Alternative)
For advanced use cases, you can also include Django-RQ views at a custom URL prefix:
# urls.py
urlpatterns += [
path('django-rq/', include('django_rq.urls'))
]
This makes views accessible at /django-rq/ instead of within the admin interface at /admin/django_rq/dashboard/.
Template URL Resolution
Templates in django-rq use a custom {% rq_url %} tag to resolve view names inside either the admin integration or standalone URLs. The tag detects the current admin namespace (when present) and falls back to the django_rq: namespace, avoiding hard-coded prefixes and keeping links working in both modes.
If you copy or override django-rq templates, load the tag library and use rq_url instead of url for django-rq views:
{% load django_rq %}
<a href="{% rq_url 'home' %}">Django RQ</a>
Usage
Putting jobs in the queue
Django-RQ allows you to easily put jobs into any of the queues defined in settings.py. It comes with a few utility functions:
enqueue- push a job to thedefaultqueue:
import django_rq
django_rq.enqueue(func, foo, bar=baz)
get_queue- returns aQueueinstance.
import django_rq
queue = django_rq.get_queue('high')
queue.enqueue(func, foo, bar=baz)
In addition to name argument, get_queue also accepts default_timeout, is_async, commit_mode, connection and queue_class arguments. For example:
queue = django_rq.get_queue('default', commit_mode='on_db_commit', is_async=True, default_timeout=360)
queue.enqueue(func, foo, bar=baz)
You can provide your own singleton Redis connection object to this function so that it will not create a new connection object for each queue definition. This will help you limit number of connections to Redis server. For example:
import django_rq
import redis
redis_cursor = redis.StrictRedis(host='', port='', db='', password='')
high_queue = django_rq.get_queue('high', connection=redis_cursor)
low_queue = django_rq.get_queue('low', connection=redis_cursor)
get_connection- accepts a single queue name argument (defaults to "default") and returns a connection to the queue's Redis server:
import django_rq
redis_conn = django_rq.get_connection('high')
get_worker- accepts optional queue names and returns a new RQWorkerinstance for specified queues (ordefaultqueue):
import django_rq
worker = django_rq.get_worker() # Returns a worker for "default" queue
worker.work()
worker = django_rq.get_worker('low', 'high') # Returns a worker for "low" and "high"
@job decorator
To easily turn a callable into an RQ task, you can also use the @job decorator that comes with django_rq:
from django_rq import job
@job
def long_running_func():
pass
long_running_func.delay() # Enqueue function in "default" queue
@job('high')
def long_running_func():
pass
long_running_func.delay() # Enqueue function in "high" queue
You can pass in any arguments that RQ's job decorator accepts:
@job('default', timeout=3600)
def long_running_func():
pass
long_running_func.delay() # Enqueue function with a timeout of 3600 seconds.
It's possible to specify default for result_ttl decorator keyword argument via DEFAULT_RESULT_TTL setting:
RQ = {
'DEFAULT_RESULT_TTL': 5000,
}
With this setting, job decorator will set result_ttl to 5000 unless it's specified explicitly or included in the queue config.
Running workers
django_rq provides a management command that starts a worker for every queue specified as arguments:
python manage.py rqworker high default low
If you want to run rqworker in burst mode, you can pass in the --burst flag:
python manage.py rqworker high default low --burst
If you need to use custom worker, job or queue classes, it is best to use global settings (see Custom queue classes and Custom job and worker classes). However, it is also possible to override such settings with command line options as follows.
To use a custom worker class, you can pass in the --worker-class flag with the path to your worker:
python manage.py rqworker high default low --worker-class 'path.to.GeventWorker'
To use a custom queue class, you can pass in the --queue-class flag with the path to your queue class:
python manage.py rqworker high default low --queue-class 'path.to.CustomQueue'
To use a custom job class, provide the --job-class flag.
Starting from version 2.10, running RQ's worker-pool is also supported:
python manage.py rqworker-pool default low medium --num-workers 4
Support for Scheduled Jobs
With RQ 1.2.0 you can use the built-in scheduler for your jobs. For example:
from datetime import datetime
from django_rq.queues import get_queue
queue = get_queue('default')
job = queue.enqueue_at(datetime(2020, 10, 10), func)
If you are using built-in scheduler you have to start workers with scheduler support:
python manage.py rqworker --with-scheduler
Support for RQ's CronScheduler
Create a cron configuration file:
# cron_config.py
from rq import cron
from myapp.tasks import send_report, sync_data
cron.register(send_report, queue_name='default', cron='0 9 * * *') # Daily at 9:00 AM
cron.register(sync_data, queue_name='high', interval=30) # Every 30 seconds
Then start the cron scheduler:
python manage.py rqcron cron_config.py
For more options, visit RQ's CronScheduler documentation.
Support for django-redis and django-redis-cache
If you have django-redis or [django-redis-cache](https://github.com/sebleier/django-re