Celery Progress Bars for Django

0.5 · active · verified Thu Apr 16

Celery Progress (celery-progress) is a Python library that provides drop-in, configurable, dependency-free progress bars for Django/Celery applications. It enables real-time progress updates for long-running asynchronous tasks directly in the web UI. Currently at version 0.5, it is actively maintained and offers simple integration with Django's URL routing and Celery's task management, including support for group results.

Common errors

Warnings

Install

Imports

Quickstart

To use `celery-progress`, first ensure Celery and Django are configured with a result backend (e.g., Redis). Add `celery_progress` to `INSTALLED_APPS` and include its URL patterns using `django.urls.path`. In your Celery task, import `ProgressRecorder`, instantiate it with `self` (from `bind=True`), and call `set_progress(current, total, description)` to update the state. In a Django view, call your task with `.delay()` to get the `task_id`, then pass this `task_id` to your template. In the frontend HTML, include the `celery_progress.js` static file and initialize `CeleryProgressBar` with the task status URL. The `onSuccess` callback can be used to handle task completion and display results.

import os
import time
from celery import shared_task
from celery_progress.backend import ProgressRecorder

# settings.py
# INSTALLED_APPS = [
#    ...,
#    'celery_progress',
# ]
# CELERY_BROKER_URL = os.environ.get('CELERY_BROKER_URL', 'redis://localhost:6379/0')
# CELERY_RESULT_BACKEND = os.environ.get('CELERY_RESULT_BACKEND', 'redis://localhost:6379/0')

# urls.py (in your project's main urls.py)
# from django.urls import path, include
# urlpatterns = [
#     ...,
#     path('celery-progress/', include('celery_progress.urls')),
# ]

@shared_task(bind=True)
def my_long_task(self, total_steps):
    progress_recorder = ProgressRecorder(self)
    for i in range(total_steps):
        time.sleep(1) # Simulate work
        progress_recorder.set_progress(i + 1, total_steps, description=f'Step {i+1} of {total_steps}')
    return 'Task Completed!'

# views.py
# from django.shortcuts import render
# from .tasks import my_long_task

# def start_task_view(request):
#     if request.method == 'POST':
#         result = my_long_task.delay(10) # Start the task asynchronously
#         return render(request, 'task_progress.html', {'task_id': result.task_id})
#     return render(request, 'start_task.html')

# task_progress.html (template)
# <div class='progress-wrapper'>
#   <div id='progress-bar' class='progress-bar' style="background-color: #68a9ef; width: 0%;">&nbsp;</div>
# </div>
# <div id="progress-bar-message">Waiting for progress to start...</div>
# <div id="celery-result"></div>
#
# {% load static %}
# <script src="{% static 'celery_progress/celery_progress.js' %}"></script>
# <script>
# document.addEventListener("DOMContentLoaded", function() {
#     var progressUrl = "{% url 'celery_progress:task_status' task_id %}";
#     CeleryProgressBar.initProgressBar(progressUrl, {
#         onSuccess: function(result, elm) {
#             document.getElementById('celery-result').innerHTML = 'Result: ' + result;
#         }
#     });
# });
# </script>

view raw JSON →