{"id":7069,"library":"celery-progress","title":"Celery Progress Bars for Django","description":"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.","status":"active","version":"0.5","language":"en","source_language":"en","source_url":"https://github.com/czue/celery-progress","tags":["django","celery","progress-bar","async-tasks","frontend","javascript"],"install":[{"cmd":"pip install celery-progress","lang":"bash","label":"Install core library"},{"cmd":"pip install celery-progress[websockets,redis]","lang":"bash","label":"Install with WebSocket support (Redis)"},{"cmd":"pip install celery-progress[websockets,rabbitmq]","lang":"bash","label":"Install with WebSocket support (RabbitMQ)"}],"dependencies":[{"reason":"Required for web integration, URL routing, and templating. The library is built specifically for Django applications.","package":"django","optional":false},{"reason":"Core dependency for asynchronous task execution and management. This library extends Celery's functionality.","package":"celery","optional":false},{"reason":"Commonly used as both Celery broker and result backend, which is essential for `celery-progress` to track task states. RabbitMQ is an alternative.","package":"redis","optional":true},{"reason":"Alternative to Redis as a Celery broker and result backend. Essential for `celery-progress` to track task states.","package":"rabbitmq","optional":true}],"imports":[{"note":"Used within Celery tasks to record progress updates.","symbol":"ProgressRecorder","correct":"from celery_progress.backend import ProgressRecorder"},{"note":"Introduced in v0.4 for tracking progress of Celery group tasks.","symbol":"GroupProgress","correct":"from celery_progress.backend import GroupProgress"},{"note":"Standard Celery decorator for creating tasks; used in conjunction with `ProgressRecorder`.","symbol":"shared_task","correct":"from celery import shared_task"}],"quickstart":{"code":"import os\nimport time\nfrom celery import shared_task\nfrom celery_progress.backend import ProgressRecorder\n\n# settings.py\n# INSTALLED_APPS = [\n#    ...,\n#    'celery_progress',\n# ]\n# CELERY_BROKER_URL = os.environ.get('CELERY_BROKER_URL', 'redis://localhost:6379/0')\n# CELERY_RESULT_BACKEND = os.environ.get('CELERY_RESULT_BACKEND', 'redis://localhost:6379/0')\n\n# urls.py (in your project's main urls.py)\n# from django.urls import path, include\n# urlpatterns = [\n#     ...,\n#     path('celery-progress/', include('celery_progress.urls')),\n# ]\n\n@shared_task(bind=True)\ndef my_long_task(self, total_steps):\n    progress_recorder = ProgressRecorder(self)\n    for i in range(total_steps):\n        time.sleep(1) # Simulate work\n        progress_recorder.set_progress(i + 1, total_steps, description=f'Step {i+1} of {total_steps}')\n    return 'Task Completed!'\n\n# views.py\n# from django.shortcuts import render\n# from .tasks import my_long_task\n\n# def start_task_view(request):\n#     if request.method == 'POST':\n#         result = my_long_task.delay(10) # Start the task asynchronously\n#         return render(request, 'task_progress.html', {'task_id': result.task_id})\n#     return render(request, 'start_task.html')\n\n# task_progress.html (template)\n# <div class='progress-wrapper'>\n#   <div id='progress-bar' class='progress-bar' style=\"background-color: #68a9ef; width: 0%;\">&nbsp;</div>\n# </div>\n# <div id=\"progress-bar-message\">Waiting for progress to start...</div>\n# <div id=\"celery-result\"></div>\n#\n# {% load static %}\n# <script src=\"{% static 'celery_progress/celery_progress.js' %}\"></script>\n# <script>\n# document.addEventListener(\"DOMContentLoaded\", function() {\n#     var progressUrl = \"{% url 'celery_progress:task_status' task_id %}\";\n#     CeleryProgressBar.initProgressBar(progressUrl, {\n#         onSuccess: function(result, elm) {\n#             document.getElementById('celery-result').innerHTML = 'Result: ' + result;\n#         }\n#     });\n# });\n# </script>","lang":"python","description":"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."},"warnings":[{"fix":"Update your project's `urls.py` to use `path('celery-progress/', include('celery_progress.urls'))` or `re_path(r'^celery-progress/', include('celery_progress.urls'))` instead of `url()` for compatibility with Django 4+.","message":"Changed URL pattern definition for Django versions >= 4.0. The library switched from `django.conf.urls.url` to `django.urls.re_path`.","severity":"breaking","affected_versions":">=0.2"},{"fix":"Wrap the `celery_progress.views.get_progress` view in your own Django view with appropriate permission checks (e.g., `@login_required` or custom permissions) and route to your protected view instead of the default `celery_progress.urls`.","message":"The default `get_progress` endpoint for `celery-progress` is publicly accessible, allowing anyone to query task statuses by `task_id`. This can pose a security risk.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure `CELERY_RESULT_BACKEND` is explicitly set in your Django settings. For example, `CELERY_RESULT_BACKEND = 'redis://localhost:6379/0'` or `CELERY_RESULT_BACKEND = 'rpc://'` (with caution).","message":"Celery requires a properly configured result backend (e.g., Redis or RabbitMQ) for `celery-progress` to function correctly. Without it, task progress and results cannot be retrieved.","severity":"gotcha","affected_versions":"All versions"},{"fix":"For applications with multiple concurrent tasks or needing persistent result storage, use a persistent result backend like Redis (`redis://`) or a database backend (`db+postgresql://`).","message":"When using Celery's RPC result backend (default in some setups), `celery-progress` may fail to pull all task states for multiple concurrent tasks because the RPC backend only allows results to be retrieved once by the client that initiated the task.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"Ensure `result.task_id` is successfully obtained from `.delay()` and passed to the template context. Verify that `path('celery-progress/', include('celery_progress.urls'))` or `re_path(r'^celery-progress/', include('celery_progress.urls'))` is correctly set up in your project's `urls.py` for modern Django versions.","cause":"The `task_id` variable is either empty, `None`, or not correctly passed from the Django view to the template, or the URL configuration for `celery_progress` is incorrect or missing.","error":"NoReverseMatch at /celery-progress/<task_id>/ Reverse for 'task_status' with arguments '('',)' not found. 1 pattern(s) tried: [u'celery_progress/(?P<task_id>[\\w-]+)/$']"},{"fix":"Double-check your `CELERY_RESULT_BACKEND` setting in Django. Ensure it's correctly pointing to a live broker/backend. Also, verify that `progress_recorder.set_progress(current, total, ...)` is always called with valid, non-None `current` and `total` values that are serializable (e.g., integers or floats).","cause":"This can occur if the Celery result backend is not properly configured, leading to issues with task state serialization or retrieval, or if the `set_progress` arguments are incorrect.","error":"TypeError: sequence item 1: expected a bytes-like object, NoneType found"},{"fix":"1. Verify Celery workers are running and processing tasks. 2. Check Celery logs for task errors. 3. Confirm `CELERY_RESULT_BACKEND` is configured and accessible. 4. Ensure the `task_id` passed to `CeleryProgressBar.initProgressBar()` is correct and the URL path is accessible via your browser's developer tools (network tab).","cause":"This often indicates a communication breakdown: either the Celery worker isn't running, the task is failing silently, the result backend isn't storing updates, or the frontend JavaScript isn't correctly polling the status URL.","error":"Progress bar does not update, stuck at 0% or 'Waiting for progress to start...' message."},{"fix":"Ensure each progress bar and its associated message/result elements in your HTML template have unique IDs. Adapt your JavaScript initialization to iterate over task IDs and initialize `CeleryProgressBar` for each unique set of elements.","cause":"When rendering multiple progress bars on a single page, the JavaScript might target elements by a non-unique ID, causing only the last element to reflect updates.","error":"DOM only updating last element of the loop while displaying multiple progress bars."}]}