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
相关产品推荐
相关产品推荐

