You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何暂停Django视图执行,等待前端用户选择结果后再保存?

解决Django视图等待用户选择后执行的问题

原方案的核心问题

你之前的思路完全不可行,原因有两个:

  • 每个HTTP请求都是独立的,view_to_pause里的request.session是请求初始化时的本地快照,后续其他请求修改的会话数据不会同步到这个请求中
  • 无限循环加sleep(1)会直接阻塞当前线程,高并发场景下会快速耗尽服务器资源,导致服务崩溃

下面是几个实用的替代方案:


方案一:缓存+前端轮询(推荐轻量场景)

利用Redis或Django内置缓存暂存方案,通过前端交互触发后续保存逻辑:

  1. 调用外部API拿到两个方案后,生成唯一任务ID,将方案存入缓存并关联该ID(设置合理过期时间,避免内存泄漏)
  2. 把任务ID和两个方案返回给前端,让用户选择
  3. 用户提交选择后,前端带着任务ID和选中项调用专门的保存视图
  4. 保存视图根据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"})

方案二:临时数据库存储(适合需要持久化的场景)

基于你提到的思路优化,增加过期清理机制避免冗余数据:

  1. 定义临时模型存储方案,关联用户ID和唯一任务标识
  2. 调用API后创建临时记录,返回任务ID和方案给前端
  3. 用户选择后,通过任务ID找到临时记录,保存选中方案,标记记录为已处理或直接删除
  4. 用定时任务(如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通信:

  1. 视图调用API获取方案后,通过WebSocket将方案推送给前端
  2. 用户选择后,通过WebSocket把选择结果发回后端
  3. 后端收到结果后立即执行保存逻辑,关闭连接

这个方案需要额外配置Channels,适合对实时性要求高的场景,复杂度相对高一些。

内容的提问来源于stack exchange,提问作者cjp1032

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 05:05:25