Django文件上传出现无限重复POST请求问题
解决Django文件上传后无限重复POST请求的问题
问题现象
通过Django搭建的文件上传界面,文件能成功上传并正常显示,但上传操作会无限重复,日志中持续出现相同的POST请求,同一文件被反复上传。
相关代码
HTML代码
<form method="post" enctype="multipart/form-data" name="upload_file"> {% csrf_token %} <input type="file" name="uploaded_file_list" multiple> <button class="rounded-full bg-violet-200 text-violet-700 block p-2" name="upload_file" value="dummy" type="submit">Ajouter des fichiers</button> </form>
views.py代码
def media_manager(request): file_manager = MediaManager.server.FileManager(django.conf.settings.USER_FILE_ROOT) # POST用于给图片关联标签 if request.method == "POST": print(request.POST) if request.POST.get("upload_file"): for uploaded_file in request.FILES.getlist("uploaded_file_list"): file_manager.add_file(uploaded_file) context_dict = {} context_dict["filtered_file_list"] = MediaManager.filters.ImageFilter(request.GET, queryset=MediaManager.models.UserImage.objects.all()) return django.shortcuts.render(request, "MediaManager/media_manager.html", context=context_dict)
FileManager.py代码
def add_file(self, uploaded_file): file_system_storage = django.core.files.storage.FileSystemStorage(location=self._user_dir_absolute_path) file_system_storage.save(uploaded_file.name, uploaded_file)
原因分析
当前处理POST请求后直接返回渲染页面,浏览器会保留POST请求的历史记录。当页面刷新(或浏览器自动重复请求)时,会重新发送相同的POST请求,导致文件被反复上传。这违反了Web开发中的Post/Redirect/Get(PRG)模式——该模式要求处理POST请求后,通过重定向让浏览器发送GET请求加载页面,从根源避免重复提交。
解决方案
修改views.py中的media_manager函数,处理完POST上传逻辑后,重定向回当前页面,而非直接渲染:
def media_manager(request): file_manager = MediaManager.server.FileManager(django.conf.settings.USER_FILE_ROOT) if request.method == "POST": if request.POST.get("upload_file"): for uploaded_file in request.FILES.getlist("uploaded_file_list"): file_manager.add_file(uploaded_file) # 处理完POST请求后,重定向到当前页面,触发GET请求 return django.shortcuts.redirect("media_manager") # 替换为你的URL配置名称,或直接用request.path context_dict = {} context_dict["filtered_file_list"] = MediaManager.filters.ImageFilter(request.GET, queryset=MediaManager.models.UserImage.objects.all()) return django.shortcuts.render(request, "MediaManager/media_manager.html", context=context_dict)
关键说明
- 使用
redirect()替代render()后,浏览器会收到302重定向响应,随后发送GET请求加载页面,此时POST请求的历史不会被保留,刷新页面只会触发GET请求,彻底避免重复上传。 - 确保
redirect()参数正确:可以是urls.py中配置的视图名称,也可以直接用request.path重定向到当前路径。 - 重定向后页面通过GET请求加载,
filtered_file_list会自动获取最新的上传文件列表,显示不受影响。
可选优化:添加上传提示
如果需要在重定向后给用户反馈,可以使用Django的messages框架:
- 在settings.py中启用messages组件:
INSTALLED_APPS = [ # 其他应用 'django.contrib.messages', ] MIDDLEWARE = [ # 其他中间件 'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', ]
- 修改视图代码添加提示:
from django.contrib import messages def media_manager(request): file_manager = MediaManager.server.FileManager(django.conf.settings.USER_FILE_ROOT) if request.method == "POST": if request.POST.get("upload_file"): upload_count = 0 for uploaded_file in request.FILES.getlist("uploaded_file_list"): file_manager.add_file(uploaded_file) upload_count += 1 messages.success(request, f"成功上传{upload_count}个文件") return django.shortcuts.redirect("media_manager") context_dict = {} context_dict["filtered_file_list"] = MediaManager.filters.ImageFilter(request.GET, queryset=MediaManager.models.UserImage.objects.all()) return django.shortcuts.render(request, "MediaManager/media_manager.html", context=context_dict)
- 在模板中添加消息显示区域:
{% if messages %} {% for message in messages %} <div class="alert alert-success">{{ message }}</div> {% endfor %} {% endif %}
内容的提问来源于stack exchange,提问作者Gautitho
相关产品推荐
相关产品推荐

