Django实现处理完成后用户下载文件的问题求助
Django生成文件后下载报错:name 'WS_file_name' is not defined
需求流程
- 用户在表单填写
lastname、firstname并上传文件newfile - Django后台处理文件,生成名为
WS_file_name+'.xlsx'的新文件 - 处理完成后展示下载按钮
- 用户点击按钮下载生成的文件
相关代码
views.py
from django.shortcuts import render from django.http import HttpResponse def index(request): if request.method == 'POST': student = StudentForm(request.POST, request.FILES) if student.is_valid(): handle_uploaded_file(request.FILES['file']) firstname= student.cleaned_data.get("firstname") lastname= student.cleaned_data.get("lastname") ### Processing ### WS_file_name = lastname + firstname + newfile Toollist_Raw = pd.read_excel(Toollist_path+Toollist_file_name) WS_file = xlsxwriter.Workbook(WS_file_name+'.xlsx') WS_file.close() file_source = WS_Path + WS_file_name+'.xlsx' Toollist_Raw.to_excel(file_source, sheet_name='CALM_Toollist',index=False) ### Process had completed, users can click download button to download the file ### context= {'username': firstname, 'version':lastname,} return render(request, 'template_Download.html', context) else: student = StudentForm() return render(request,"template_Form.html",{'form':student}) ##### Download Functions ##### import os from django.http import FileResponse def download_file(request): # Define Django project base directory BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # Define file name filename = WS_file_name+'.xlsx' # Define the full file path filepath = BASE_DIR + '/Capital_Report_Website/Download_Files/Baseline_Cleanup_Toollist_vs_CALM_Download/' + filename +'.xlsx' return FileResponse(open(filepath, 'rb'), as_attachment=True)
template_Form.html
<form method="POST" class="post-form" enctype="multipart/form-data"> {% csrf_token %} {{ form.as_p }} <button type="submit" class="save btn btn-default">Generate Report</button> </form>
template_Download.html
<h3>Hi, {{username}} your toollist {{version}} vs CALM report is completed.</h3> <a href="http://localhost/toollistvscalm/download/">Download</a>
urls.py
urlpatterns = [ path('admin/', admin.site.urls), path('toollistvscalm/', views.index), path('toollistvscalm/download/', views.download_file), ]
报错信息
name 'WS_file_name' is not defined
问题原因
WS_file_name是index视图处理POST请求时的局部变量,download_file是独立的视图函数,无法直接访问该变量,导致报错。同时原代码中download_file的文件路径拼接重复添加了.xlsx后缀,也会导致文件找不到。
解决方案
方案一:使用Django Session传递文件名
- 修改
index视图,将生成的文件名存入session:
# 在return render前添加 request.session['ws_file_name'] = WS_file_name context= {'username': firstname, 'version':lastname,} return render(request, 'template_Download.html', context)
- 修改
download_file视图,从session中获取文件名并修正路径:
import os from django.http import FileResponse, Http404 def download_file(request): BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 从session获取文件名 ws_file_name = request.session.get('ws_file_name') if not ws_file_name: raise Http404("File not found") filename = f"{ws_file_name}.xlsx" # 拼接正确路径(避免重复加.xlsx) filepath = os.path.join(BASE_DIR, 'Capital_Report_Website/Download_Files/Baseline_Cleanup_Toollist_vs_CALM_Download', filename) # 检查文件是否存在 if not os.path.exists(filepath): raise Http404("File not found") return FileResponse(open(filepath, 'rb'), as_attachment=True, filename=filename)
方案二:通过URL传递文件名(更直观)
- 修改
urls.py,给下载路径添加文件名参数:
from django.urls import path from . import views urlpatterns = [ path('admin/', admin.site.urls), path('toollistvscalm/', views.index), # 添加文件名参数 path('toollistvscalm/download/<str:filename>/', views.download_file, name='download_file'), ]
- 修改
index视图,将文件名传入模板上下文:
context= { 'username': firstname, 'version':lastname, 'ws_file_name': WS_file_name # 添加文件名到上下文 } return render(request, 'template_Download.html', context)
- 修改
template_Download.html的下载链接,使用Django的URL反向解析传递文件名:
<h3>Hi, {{username}} your toollist {{version}} vs CALM report is completed.</h3> <a href="{% url 'download_file' filename=ws_file_name %}">Download</a>
- 修改
download_file视图,接收文件名参数并处理:
import os from django.http import FileResponse, Http404 def download_file(request, filename): BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) full_filename = f"{filename}.xlsx" filepath = os.path.join(BASE_DIR, 'Capital_Report_Website/Download_Files/Baseline_Cleanup_Toollist_vs_CALM_Download', full_filename) if not os.path.exists(filepath): raise Http404("File not found") return FileResponse(open(filepath, 'rb'), as_attachment=True, filename=full_filename)
额外优化提示
原代码中使用xlsxwriter.Workbook创建文件后直接关闭,随后又用Toollist_Raw.to_excel写入内容,这会导致文件内容被覆盖或写入失败。可以简化为:
# 替换原Processing部分的代码 WS_file_name = lastname + firstname + newfile file_source = os.path.join(WS_Path, f"{WS_file_name}.xlsx") Toollist_Raw = pd.read_excel(os.path.join(Toollist_path, Toollist_file_name)) Toollist_Raw.to_excel(file_source, sheet_name='CALM_Toollist', index=False, engine='xlsxwriter')
内容的提问来源于stack exchange,提问作者CanaryTheBird
相关产品推荐
相关产品推荐

