求助:如何在Django OCR应用中使用Celery进度条展示任务进度
如何在Django OCR应用中集成celery-progress-bar展示实时处理进度?
嘿,我帮你一步步搞定这个celery-progress-bar的集成问题!你的OCR流程很清晰,刚好适合用异步任务+实时进度条来优化用户体验——毕竟长时间让用户盯着加载圈太不友好了。下面是具体的实现步骤,完全贴合你给出的代码结构来调整:
第一步:安装依赖与基础配置
首先得把必要的包装起来,同时配置Celery的消息中间件(这里用Redis做示例,你也可以用RabbitMQ):
pip install celery celery-progress redis
然后在你的Django项目settings.py里添加Celery配置:
# settings.py CELERY_BROKER_URL = 'redis://localhost:6379/0' # Redis地址,根据你的实际部署调整 CELERY_RESULT_BACKEND = 'redis://localhost:6379/0' CELERY_ACCEPT_CONTENT = ['json'] CELERY_TASK_SERIALIZER = 'json' CELERY_RESULT_SERIALIZER = 'json'
第二步:把OCR逻辑迁移到Celery异步任务
因为要实时更新进度,必须把耗时的OCR处理放到Celery异步任务里。新建一个tasks.py文件,把你的处理逻辑移进去,并用celery-progress的ProgressRecorder来更新进度:
# tasks.py from celery import shared_task from celery_progress.backend import ProgressRecorder # 假设你的图像处理、分割、预测函数放在utils.py里,按需调整导入路径 from .utils import image_processing, character_segmentation, predict @shared_task(bind=True) def process_ocr_task(self, image_path): progress_recorder = ProgressRecorder(self) # 先预估总步骤数:图像处理(1步)+字符分割(1步)+每个字符预测(N步) total_steps = 2 # 先初始化前两步的计数 # 1. 图像处理阶段 cleared_image = image_processing(image_path) progress_recorder.set_progress(1, total_steps, description="完成图像处理") # 2. 字符分割阶段 segmented_characters = character_segmentation(cleared_image) # 更新总步骤数:加上字符预测的数量 total_steps += len(segmented_characters) progress_recorder.set_progress(2, total_steps, description="完成字符分割,开始识别字符") # 3. 逐个字符预测阶段 predicted = [] current_step = 2 for idx, character in enumerate(segmented_characters): prediction = predict(character) predicted.append(prediction) current_step += 1 progress_recorder.set_progress( current_step, total_steps, description=f"正在处理第{idx+1}/{len(segmented_characters)}个字符" ) # 返回最终结果 return {"predicted_text": "".join(predicted)}
第三步:修改视图触发任务并提供进度查询
调整你的views.py,把原来的同步处理改成触发异步任务,并新增一个接口供前端查询进度:
# views.py from django.shortcuts import render from django.http import JsonResponse from django.conf import settings import os from .tasks import process_ocr_task from celery_progress.backend import Progress def upload_and_process(request): if request.method == 'POST' and request.FILES.get('image'): # 先保存上传的图片到媒体目录(确保MEDIA_ROOT配置正确且有写入权限) image_file = request.FILES['image'] temp_image_path = os.path.join(settings.MEDIA_ROOT, 'temp', image_file.name) os.makedirs(os.path.dirname(temp_image_path), exist_ok=True) with open(temp_image_path, 'wb+') as destination: for chunk in image_file.chunks(): destination.write(chunk) # 触发Celery异步任务 task = process_ocr_task.delay(temp_image_path) # 返回任务ID,前端用这个查询进度 return JsonResponse({"task_id": task.id}) # GET请求返回上传页面 return render(request, 'ocr_upload.html') def get_ocr_progress(request, task_id): # 查询任务进度并返回 progress = Progress(task_id) return JsonResponse(progress.get_info())
第四步:前端实现进度条展示
新建一个模板文件ocr_upload.html,实现图片上传、进度条更新和结果展示的逻辑:
<!-- templates/ocr_upload.html --> <!DOCTYPE html> <html> <head> <title>OCR文字识别</title> <style> .progress-container { width: 100%; height: 24px; border: 1px solid #ccc; border-radius: 4px; margin: 20px 0; display: none; } .progress-bar { height: 100%; background-color: #4CAF50; width: 0%; transition: width 0.3s ease; } </style> </head> <body> <h1>上传图片进行OCR识别</h1> <form id="uploadForm" enctype="multipart/form-data"> <input type="file" name="image" accept="image/*" required> <button type="submit">开始识别</button> </form> <div class="progress-container" id="progressContainer"> <div class="progress-bar" id="progressBar"></div> <p id="progressText"></p> </div> <div id="resultArea" style="margin-top: 20px; font-size: 1.2em;"></div> <script> document.getElementById('uploadForm').addEventListener('submit', async (e) => { e.preventDefault(); const formData = new FormData(e.target); // 上传图片并获取任务ID const uploadRes = await fetch('/upload/', { method: 'POST', body: formData }); const { task_id } = await uploadRes.json(); // 显示进度容器 document.getElementById('progressContainer').style.display = 'block'; // 轮询查询进度 const progressInterval = setInterval(async () => { const progressRes = await fetch(`/progress/${task_id}/`); const progressData = await progressRes.json(); // 更新进度条和文本 document.getElementById('progressBar').style.width = `${progressData.percent}%`; document.getElementById('progressText').textContent = `${progressData.description} (${progressData.percent}%)`; // 任务完成后停止轮询并展示结果 if (progressData.completed) { clearInterval(progressInterval); document.getElementById('resultArea').textContent = `识别结果:${progressData.result.predicted_text}`; } }, 500); // 每500毫秒查询一次进度 }); </script> </body> </html>
最后:配置URL并启动服务
在项目的urls.py里添加对应的路由:
# urls.py from django.urls import path from . import views urlpatterns = [ path('upload/', views.upload_and_process, name='ocr_upload'), path('progress/<str:task_id>/', views.get_ocr_progress, name='ocr_progress'), ]
然后启动必要的服务:
- 启动Redis服务(如果用Redis做Broker)
- 启动Celery Worker:
celery -A 你的项目名称 worker --loglevel=info
- 启动Django开发服务器:
python manage.py runserver
这样用户上传图片后,就能看到实时更新的进度条,体验会好很多!
内容的提问来源于stack exchange,提问作者Harshit Mahajan
相关产品推荐
相关产品推荐

