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

Django中如何在浏览器跳转前追踪表单上传进度?

实现Django表单上传进度追踪方案

当然可以实现上传进度追踪,但原生表单的默认提交方式会直接跳转页面,没法在当前页监听进度。得用JavaScript拦截表单提交,通过AJAX完成上传并实时获取进度数据。

1. 修改Django模板,添加进度显示元素和拦截逻辑

在原表单基础上,增加进度条容器,并给提交按钮绑定自定义提交事件:

{% extends "base.html" %}
{% block content %}
{% if form.errors %}
        <p style="color: red;">
            Please correct the error{{ form.errors|pluralize }} below.
        </p>
{% endif %}
<div data-role="content" style="padding: 15px">
    <!-- 新增进度条容器 -->
    <div style="width: 100%; height: 20px; border: 1px solid #ccc; margin-bottom: 10px; display: none;" id="progress-container">
        <div style="height: 100%; width: 0%; background-color: #4CAF50; transition: width 0.3s;" id="progress-bar"></div>
    </div>
    <p id="progress-text" style="display: none;"></p>

    <form id="upload-form" action="{% url 'success' %}" method="POST" enctype="multipart/form-data">
            {% csrf_token %}
            {{ form.errors }}
            {{ form.non_field_errors }}
            {{ form.as_table }}
        <input type="submit" value="Submit" id="Save">
    </form>
</div>

<script>
document.getElementById('upload-form').addEventListener('submit', function(e) {
    // 阻止默认表单提交
    e.preventDefault();
    
    const form = this;
    const formData = new FormData(form);
    const progressContainer = document.getElementById('progress-container');
    const progressBar = document.getElementById('progress-bar');
    const progressText = document.getElementById('progress-text');
    
    // 显示进度条
    progressContainer.style.display = 'block';
    progressText.style.display = 'block';
    
    // 创建XHR对象
    const xhr = new XMLHttpRequest();
    
    // 监听上传进度
    xhr.upload.addEventListener('progress', function(e) {
        if (e.lengthComputable) {
            const percentComplete = (e.loaded / e.total) * 100;
            progressBar.style.width = percentComplete + '%';
            progressText.textContent = `已上传:${Math.round(percentComplete)}%`;
        }
    });
    
    // 上传完成处理
    xhr.addEventListener('load', function() {
        if (xhr.status === 200) {
            // 上传成功,跳转到成功页面
            window.location.href = form.action;
        } else {
            progressText.textContent = '上传失败,请重试';
            progressBar.style.backgroundColor = '#f44336';
        }
    });
    
    // 发送请求
    xhr.open('POST', form.action);
    // 带上CSRF令牌,Django需要验证
    xhr.setRequestHeader('X-CSRFToken', document.querySelector('[name=csrfmiddlewaretoken]').value);
    xhr.send(formData);
});
</script>
{% endblock %}

2. 调整Django视图(可选)

如果需要在上传完成后返回自定义响应,或者处理大文件上传的额外逻辑,可以修改对应的视图函数:

from django.http import JsonResponse
from django.shortcuts import redirect, render
from .forms import YourForm  # 替换成你的表单类

def success_view(request):
    if request.method == 'POST':
        form = YourForm(request.POST, request.FILES)
        if form.is_valid():
            form.save()
            # AJAX请求返回JSON响应
            if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                return JsonResponse({'status': 'success'})
            # 非AJAX请求直接跳转
            return redirect('success_page')
        else:
            if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                return JsonResponse({'status': 'error', 'errors': form.errors}, status=400)
    # GET请求返回表单页面
    return render(request, 'your_template.html', {'form': YourForm()})

注意事项

  • 确保Django的CSRF令牌正确传递,否则请求会被拒绝
  • 大文件上传需要调整Django配置(比如MAX_UPLOAD_SIZE)和服务器限制(Nginx/Apache的上传大小设置)
  • 也可以用Fetch API替代XMLHttpRequest,核心都是监听progress事件

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 13:05:19