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

Django 5 REST Framework:如何在API请求处理前返回加载提示?

解决方案

HTTP协议本身是单次请求对应单次响应,没法在同一个请求里先返回加载提示,再返回最终处理结果。但可以通过以下两种方式实现类似需求:

方案一:前端配合后端异步任务(推荐)

这是最符合HTTP规范、用户体验最好的方式,核心流程如下:

  1. 前端发起请求后,后端立即返回一个任务ID,前端同步显示"Loading... Please wait."
  2. 后端在后台异步执行耗时任务
  3. 前端通过轮询或WebSocket,用任务ID查询任务状态,直到任务完成后获取最终结果

具体实现(基于Celery异步任务)

1. 基础Celery配置(以Redis为消息中间件)

# project/celery.py
import os
from celery import Celery

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings')
app = Celery('project')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()

2. 定义耗时任务

# app/tasks.py
from celery import shared_task
import time

@shared_task
def long_running_task():
    # 模拟耗时操作,替换为实际业务逻辑
    time.sleep(10)
    return {"result": "耗时任务处理完成"}

3. 修改API视图

from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .tasks import long_running_task

class SomeView(APIView):
    authentication_classes = [SessionAuthentication, BasicAuthentication]
    permission_classes = [IsAuthenticated]

    def get(self, request):
        # 启动异步任务
        task = long_running_task.delay()
        # 返回任务ID,供前端查询状态
        return Response({"task_id": task.id}, status=status.HTTP_202_ACCEPTED)

# 新增任务状态查询视图
class TaskStatusView(APIView):
    authentication_classes = [SessionAuthentication, BasicAuthentication]
    permission_classes = [IsAuthenticated]

    def get(self, request, task_id):
        from celery.result import AsyncResult
        task = AsyncResult(task_id)
        if task.state == 'PENDING':
            response = {"state": task.state, "status": "任务正在处理中..."}
        elif task.state == 'SUCCESS':
            response = {"state": task.state, "result": task.result}
        else:
            response = {"state": task.state, "status": f"任务异常: {task.info}"}
        return Response(response)

4. 前端示例(JavaScript)

async function fetchData() {
    const loadingElement = document.getElementById('loading');
    loadingElement.textContent = 'Loading... Please wait.';
    
    // 发起任务请求
    const taskResponse = await fetch('/api/some-view/', {
        method: 'GET',
        credentials: 'include'
    });
    const taskData = await taskResponse.json();
    const taskId = taskData.task_id;
    
    // 轮询任务状态
    const pollInterval = setInterval(async () => {
        const statusResponse = await fetch(`/api/task-status/${taskId}/`, {
            method: 'GET',
            credentials: 'include'
        });
        const statusData = await statusResponse.json();
        
        if (statusData.state === 'SUCCESS') {
            clearInterval(pollInterval);
            loadingElement.textContent = '';
            // 展示最终结果
            document.getElementById('result').textContent = JSON.stringify(statusData.result);
        } else if (statusData.state !== 'PENDING') {
            clearInterval(pollInterval);
            loadingElement.textContent = statusData.status;
        }
    }, 1000);
}

方案二:流式响应(不推荐,兼容性差)

利用Django的StreamingHttpResponse分块返回内容,先输出加载提示,再执行耗时任务后输出结果。但这种方式在多数浏览器中会等到全部内容加载完成后才显示,体验不佳,且不符合REST API的设计规范。

代码示例

from django.http import StreamingHttpResponse
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView
import time

class SomeView(APIView):
    authentication_classes = [SessionAuthentication, BasicAuthentication]
    permission_classes = [IsAuthenticated]

    def get(self, request):
        def stream_response():
            # 先输出加载提示
            yield "Loading... Please wait.\n"
            # 执行耗时任务
            time.sleep(10)
            # 输出最终结果
            yield '{"result": "耗时任务处理完成"}'
        
        return StreamingHttpResponse(stream_response(), content_type='text/plain')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 21:33:15