如何暂停Django视图执行,等待前端用户选择结果后再保存?
解决Django视图等待用户选择后执行的问题
原方案的核心问题
你之前的思路完全不可行,原因有两个:
- 每个HTTP请求都是独立的,
view_to_pause里的request.session是请求初始化时的本地快照,后续其他请求修改的会话数据不会同步到这个请求中 - 无限循环加
sleep(1)会直接阻塞当前线程,高并发场景下会快速耗尽服务器资源,导致服务崩溃
下面是几个实用的替代方案:
方案一:缓存+前端轮询(推荐轻量场景)
利用Redis或Django内置缓存暂存方案,通过前端交互触发后续保存逻辑:
- 调用外部API拿到两个方案后,生成唯一任务ID,将方案存入缓存并关联该ID(设置合理过期时间,避免内存泄漏)
- 把任务ID和两个方案返回给前端,让用户选择
- 用户提交选择后,前端带着任务ID和选中项调用专门的保存视图
- 保存视图根据ID从缓存取出方案,执行保存逻辑后清理缓存
代码示例:
from django.core.cache import cache import uuid from django.http import JsonResponse def fetch_solutions(request): # 调用外部API获取两个方案 solution1 = call_external_api(option="1") solution2 = call_external_api(option="2") # 生成唯一任务ID task_id = str(uuid.uuid4()) # 存入缓存,1小时后自动过期 cache.set(task_id, {"sol1": solution1, "sol2": solution2}, 3600) return JsonResponse({ "task_id": task_id, "solutions": [solution1, solution2] }) def save_selected(request): if request.method != "POST": return JsonResponse({"error": "仅支持POST请求"}, status=400) task_id = request.POST.get("task_id") selected_idx = request.POST.get("selected_idx") # 从缓存获取方案 solutions = cache.get(task_id) if not solutions: return JsonResponse({"error": "任务已过期或不存在"}, status=400) # 获取选中方案并保存 selected_sol = solutions["sol1"] if selected_idx == "0" else solutions["sol2"] code_that_saves_result(selected_sol) # 清理缓存 cache.delete(task_id) return JsonResponse({"status": "success"})
方案二:临时数据库存储(适合需要持久化的场景)
基于你提到的思路优化,增加过期清理机制避免冗余数据:
- 定义临时模型存储方案,关联用户ID和唯一任务标识
- 调用API后创建临时记录,返回任务ID和方案给前端
- 用户选择后,通过任务ID找到临时记录,保存选中方案,标记记录为已处理或直接删除
- 用定时任务(如Celery Beat)定期清理过期未处理的临时记录
代码示例:
from django.db import models import uuid from django.http import JsonResponse from django.utils import timezone # 临时方案模型 class TempSolution(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) task_id = models.UUIDField(default=uuid.uuid4, unique=True) solution1 = models.TextField() solution2 = models.TextField() created_at = models.DateTimeField(auto_now_add=True) is_processed = models.BooleanField(default=False) def fetch_solutions(request): solution1 = call_external_api(option="1") solution2 = call_external_api(option="2") # 创建临时记录 temp_sol = TempSolution.objects.create( user=request.user, solution1=solution1, solution2=solution2 ) return JsonResponse({ "task_id": str(temp_sol.task_id), "solutions": [solution1, solution2] }) def save_selected(request): if request.method != "POST": return JsonResponse({"error": "仅支持POST请求"}, status=400) task_id = request.POST.get("task_id") selected_idx = request.POST.get("selected_idx") try: temp_sol = TempSolution.objects.get( task_id=task_id, user=request.user, is_processed=False, created_at__gte=timezone.now() - timezone.timedelta(hours=1) ) except TempSolution.DoesNotExist: return JsonResponse({"error": "无效或过期任务"}, status=400) selected_sol = temp_sol.solution1 if selected_idx == "0" else temp_sol.solution2 code_that_saves_result(selected_sol) # 标记为已处理或直接删除 temp_sol.is_processed = True temp_sol.save() # 或直接删除:temp_sol.delete() return JsonResponse({"status": "success"})
方案三:WebSocket实时通信(适合高实时性场景)
如果需要即时响应,可以用Django Channels实现WebSocket通信:
- 视图调用API获取方案后,通过WebSocket将方案推送给前端
- 用户选择后,通过WebSocket把选择结果发回后端
- 后端收到结果后立即执行保存逻辑,关闭连接
这个方案需要额外配置Channels,适合对实时性要求高的场景,复杂度相对高一些。
内容的提问来源于stack exchange,提问作者cjp1032
相关产品推荐
相关产品推荐

