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

Django项目中如何同时实现模板渲染与文件下载功能?

问题

在基于Django开发的Web应用中,我实现了Excel文件上传功能,可基于文件数据完成特定计算并导出更新后的文件。但我还希望同时在模板中展示特定信息。以下是我在views.py中尝试的代码:

context = {'mttr_count': mttr_count, 'mttr_avg': mttr_avg, 'data':sheet}
        
response = HttpResponse(content_type='application/ms-excel')
response['Content-Disposition'] = 'attachment; filename="mttr.xls"'
rendered = render_to_string('mttr/mttr-output.html', context)
response = HttpResponse(rendered)
wb.save(response)
return response

但该代码未达到预期效果。请问如何实现点击提交按钮后,既渲染携带上下文数据的mttr.html模板,又完成修改后文件的下载?

解决方案

HTTP协议一次请求只能返回一个响应,没法在同一个视图里同时返回页面渲染和文件下载,可通过以下两种方式实现需求:

方法1:先渲染结果页面,前端自动触发下载

  1. 拆分视图逻辑:

    • 第一个视图处理文件上传、计算,把生成的Excel存到服务器临时目录,同时将计算结果存入会话或数据库。
    • 重定向到结果展示视图,从会话/数据库取数据渲染mttr.html。

    示例代码:

    import os
    from django.conf import settings
    from django.shortcuts import redirect, render
    
    def upload_and_calculate(request):
        if request.method == 'POST':
            # 此处省略文件上传、数据计算、生成wb对象的逻辑
            mttr_count = ...
            mttr_avg = ...
    
            # 保存Excel到临时目录
            temp_dir = os.path.join(settings.MEDIA_ROOT, 'temp')
            os.makedirs(temp_dir, exist_ok=True)
            temp_file_path = os.path.join(temp_dir, 'mttr.xls')
            wb.save(temp_file_path)
    
            # 计算结果存入会话
            request.session['mttr_count'] = mttr_count
            request.session['mttr_avg'] = mttr_avg
            request.session['temp_file'] = 'mttr.xls'
    
            return redirect('show_mttr_result')
        return render(request, 'mttr/upload.html')
    
    def show_mttr_result(request):
        context = {
            'mttr_count': request.session.get('mttr_count'),
            'mttr_avg': request.session.get('mttr_avg')
        }
        return render(request, 'mttr/mttr.html', context)
    
  2. 模板添加自动下载脚本:
    在mttr.html底部加入JS,页面加载后自动发起下载请求:

    <script>
        window.addEventListener('load', function() {
            window.location.href = "{% url 'download_mttr' %}";
        });
    </script>
    
  3. 新增下载视图:

    def download_mttr(request):
        temp_file = request.session.get('temp_file')
        temp_file_path = os.path.join(settings.MEDIA_ROOT, 'temp', temp_file)
        
        if os.path.exists(temp_file_path):
            with open(temp_file_path, 'rb') as f:
                response = HttpResponse(f.read(), content_type='application/ms-excel')
                response['Content-Disposition'] = f'attachment; filename="{temp_file}"'
                # 下载后删除临时文件,清理会话
                os.remove(temp_file_path)
                del request.session['temp_file']
                return response
        return HttpResponse("文件不存在", status=404)
    

方法2:结果页面添加手动下载按钮

如果不需要自动下载,可在结果页面展示数据的同时,提供下载按钮供用户手动触发:

  1. 视图逻辑调整:

    def upload_and_show(request):
        if request.method == 'POST':
            # 省略上传、计算、保存Excel到临时目录的逻辑
            mttr_count = ...
            mttr_avg = ...
            temp_file_name = 'mttr.xls'
            
            context = {
                'mttr_count': mttr_count,
                'mttr_avg': mttr_avg,
                'download_url': reverse('download_mttr', kwargs={'file_name': temp_file_name})
            }
            return render(request, 'mttr/mttr.html', context)
        return render(request, 'mttr/upload.html')
    
  2. 模板添加下载按钮:

    <a href="{{ download_url }}" class="btn">下载更新后的Excel文件</a>
    
  3. 下载视图适配参数:

    def download_mttr(request, file_name):
        temp_file_path = os.path.join(settings.MEDIA_ROOT, 'temp', file_name)
        if os.path.exists(temp_file_path):
            with open(temp_file_path, 'rb') as f:
                response = HttpResponse(f.read(), content_type='application/ms-excel')
                response['Content-Disposition'] = f'attachment; filename="{file_name}"'
                os.remove(temp_file_path)
                return response
        return HttpResponse("文件不存在", status=404)
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 09:01:00