Package: celery-progress
Celery Progress Bars for DjangoDrop in, dependency-free progress bars for your Django/Celery applications.Super simple setup. Lots of customization available.DemoCelery Progress Bar demo on Build With DjangoGithub demo application: build a download progress bar for DjangoStarting with Celery can be challenging,eeintechbuilt a completeDjango demo applicationalong with astep-by-step guideto get you started on building your own progress bar!InstallationIf you haven't already, make sure you have properlyset up celery in your project.Then install this library:pipinstallcelery-progressUsagePrerequisitesFirst addcelery_progressto yourINSTALLED_APPSinsettings.py.Then add the following url config to your mainurls.py:fromdjango.urlsimportpath,includeurlpatterns=[# your project's patterns here...path(r'^celery-progress/',include('celery_progress.urls')),# add this line (the endpoint is configurable)]Recording ProgressIn your task you should add something like this:fromceleryimportshared_taskfromcelery_progress.backendimportProgressRecorderimporttime@shared_task(bind=True)defmy_task(self,seconds):progress_recorder=ProgressRecorder(self)result=0foriinrange(seconds):time.sleep(1)result+=iprogress_recorder.set_progress(i+1,seconds)returnresultYou can add an optional progress description like this:progress_recorder.set_progress(i+1,seconds,description='my progress description')Displaying progressIn the view where you call the task you need to get the task ID like so:views.pydefprogress_view(request):result=my_task.delay(10)returnrender(request,'display_progress.html',context={'task_id':result.task_id})Then in the page you want to show the progress bar you just do the following.Add the following HTML wherever you want your progress bar to appear:display_progress.html<divclass='progress-wrapper'><divid='progress-bar'class='progress-bar'style="background-color: #68a9ef; width: 0%;">&nbsp;</div></div><divid="progress-bar-message">Waiting for progress to start...</div>Import the javascript file.display_progress.html<scriptsrc="{% static 'celery_progress/celery_progress.js' %}"></script>Initialize the progress bar:// vanilla JS versiondocument.addEventListener("DOMContentLoaded",function(){varprogressUrl="{% url 'celery_progress:task_status' task_id %}";CeleryProgressBar.initProgressBar(progressUrl);});or// JQuery$(function(){varprogressUrl="{% url 'celery_progress:task_status' task_id %}";CeleryProgressBar.initProgressBar(progressUrl)});Displaying the result of a taskIf you'd like you can also display the result of your task on the front end.To do that follow the steps below. Result handling can also be customized.Initialize the result block:This is all that's needed to render the result on the page.display_progress.html<divid="celery-result"></div>But more likely you will want to customize how the result looks, which can be done as below:// JQueryvarprogressUrl="{% url 'celery_progress:task_status' task_id %}";functioncustomResult(resultElement,result){$(resultElement).append($('<p>').text('Sum of all seconds is '+result));}$(function(){CeleryProgressBar.initProgressBar(progressUrl,{onResult:customResult,})});CustomizationTheinitProgressBarfunction takes an optional object of options. The following options are supported:OptionWhat it doesDefault ValuepollIntervalHow frequently to poll for progress (in milliseconds)500progressBarIdOverride the ID used for the progress bar'progress-bar'progressBarMessageIdOverride the ID used for the progress bar message'progress-bar-message'progressBarElementOverride theelementused for the progress bar. If specified, progressBarId will be ignored.document.getElementById(progressBarId)progressBarMessageElementOverride theelementused for the progress bar message. If specified, progressBarMessageId will be ignored.document.getElementById(progressBarMessageId)resultElementIdOverride the ID used for the result'celery-result'resultElementOverride theelementused for the result. If specified, resultElementId will be ignored.document.getElementById(resultElementId)onProgressfunction to call when progress is updatedonProgressDefaultonSuccessfunction to call when progress successfully completesonSuccessDefaultonErrorfunction to call on a known error with no specified handleronErrorDefaultonRetryfunction to call when a task attempts to retryonRetryDefaultonIgnoredfunction to call when a task result is ignoredonIgnoredDefaultonTaskErrorfunction to call when progress completes with an erroronErroronNetworkErrorfunction to call on a network error (ignored by WebSocket)onErroronHttpErrorfunction to call on a non-200 response (ignored by WebSocket)onErroronDataErrorfunction to call on a response that's not JSON or has invalid schema due to a programming erroronErroronResultfunction to call when returned non empty resultCeleryProgressBar.onResultDefaultbarColorsdictionary containing color values for various progress bar states. Colors that are not specified will defer to defaultsbarColorsDefaultdefaultMessagesdictionary containing default messages that can be overriddensee belowThebarColorsoption allows you to customize the color of each progress bar state by passing a dictionary of key-value pairs ofstate: #hexcode. The defaults are shown below.StateHex CodeImage Colorsuccess#76ce60error#dc4f63progress#68a9efignored#7a7a7aThedefaultMessagesoption allows you to override some default messages in the UI. At the moment these are:Message IdWhen ShownDefault ValuewaitingTask is waiting to start'Waiting for task to start...'startedTask has started but reports no progress'Task started...'WebSocket SupportAdditionally, this library offers WebSocket support usingDjango Channelscourtesy ofEJH2.A working example project leveraging WebSockets isavailable here.To use WebSockets, install withpip install celery-progress[websockets,redis]orpip install celery-progress[websockets,rabbitmq](depending on broker dependencies).SeeWebSocketProgressRecorderandwebsockets.jsfor details.Securing the get_progress endpointBy default, anyone can see the status and result of any task by accessing/celery-progress/<task_id>To limit access, you need to wrapget_progress()in a view of your own which implements the permissions check, and create a new url routing to point to your view.  Make sure to remove any existing (unprotected) celery progress urls from your root urlconf at the same time.For example, requiring login with a class-based view:# views.pyfromcelery_progress.viewsimportget_progressfromdjango.contrib.auth.mixinsimportLoginRequiredMixinfromdjango.views.genericimportViewclassTaskStatus(LoginRequiredMixin,View):defget(self,request,task_id,*args,**kwargs):# Other checks could go herereturnget_progress(request,task_id=task_id)# urls.pyfromdjango.urlsimportpathfrom.importviewsurlpatterns=[...path('task-status/<uuid:task_id>',views.TaskStatus.as_view(),name='task_status'),...]Requiring login with a function-based view:# views.pyfromcelery_progress.viewsimportget_progressfromdjango.contrib.auth.decoratorsimportlogin_required@login_requireddeftask_status(request,task_id):# Other checks could go herereturnget_progress(request,task_id)# urls.pyfromdjango.urlsimportpathfrom.importviewsurlpatterns=[...path('task-status/<uuid:task_id>',views.task_status,name='task_status'),...]Any links to'celery_progress:task_status'will need to be changed to point to your new endpoint.