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

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框架:

  1. 在settings.py中启用messages组件:
INSTALLED_APPS = [
    # 其他应用
    'django.contrib.messages',
]

MIDDLEWARE = [
    # 其他中间件
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
]
  1. 修改视图代码添加提示:
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)
  1. 在模板中添加消息显示区域:
{% if messages %}
    {% for message in messages %}
        <div class="alert alert-success">{{ message }}</div>
    {% endfor %}
{% endif %}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 08:01:02