使用Django无法下载自定义Excel模板是什么原因?该如何实现下载功能?
问题排查与修正方案
现有代码的核心问题列表
- 前端表单配置错误:
- 提交按钮错误设置了两个
type属性,type="button"会导致点击后不会触发表单提交 - 表单
action路径与urls配置不匹配,且method误设为GET,表单提交参数应走POST action写死相对路径容易出错,应该用Django模板的url反向解析
- 提交按钮错误设置了两个
- 后端视图逻辑缺失:
create_template视图的POST分支没有任何业务逻辑,既没有校验表单,也没有生成Excel、返回下载响应的代码- Excel生成函数直接将文件写入服务器本地磁盘,没有将文件流返回给用户
- 表单参数没有做格式转换:用户输入的sheet名、列名都是以符号分隔的字符串,没有拆分就直接遍历会得到单个字符,年份也没有生成起止区间的列表
- 函数命名混淆:生成Excel的函数命名为
create_form,和表单类名混淆,可读性差
修正后的完整代码
1. my_app/templates/my_app/create_template.html
{% extends "my_app/base.html" %} {% block content %} <form action="{% url 'my-create-template' %}" method="POST"> {% csrf_token %} <h1>Create your template</h1> <div class="item"> <table> {{ form.as_table }} </table> <p>提示:多个sheet名、列名请用英文逗号分隔</p> </div> <div class="btn-block"> <input type="submit" value="Create and Download!"/> </div> </form> {% endblock content %}
2. my_app/views.py
from django.http import HttpResponse from django.shortcuts import render import xlsxwriter from django.forms import Form, CharField, ChoiceField def home(request): return render(request, 'my_app/home.html') class TemplateForm(Form): doc_name = CharField(label='Document name') sheetnames = CharField(label='Sheetnames') choices = [] for year in range (1900, 2050): choices.append( (year, year) ) year1 = ChoiceField(label='Starting Year', initial=2021, choices=choices) year2 = ChoiceField(label='Ending Year', initial=2022, choices=choices) row_names = CharField(label='Column names') def create_template(request): if request.method == 'GET': form = TemplateForm() return render(request, 'my_app/create_template.html', {'form':form}) # POST请求处理逻辑 form = TemplateForm(request.POST) if form.is_valid(): data = form.cleaned_data # 处理表单参数 doc_name = data['doc_name'] # 拆分sheet名,按英文逗号分割,去空格 sheetnames = [i.strip() for i in data['sheetnames'].split(',') if i.strip()] # 生成年份区间列表 start_year = int(data['year1']) end_year = int(data['year2']) years = list(range(start_year, end_year+1)) # 拆分列名 row_names = [i.strip() for i in data['row_names'].split(',') if i.strip()] # 生成HttpResponse对象,设置Excel对应的mime类型 response = HttpResponse(content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') # 设置响应头,指定下载文件名 response['Content-Disposition'] = f'attachment; filename="{doc_name}_template.xlsx"' # 直接将Excel写入response对象,不需要存服务器本地 workbook = xlsxwriter.Workbook(response) worksheet_introduction = workbook.add_worksheet("introduction") for sheet_name in sheetnames: worksheet_data = workbook.add_worksheet(sheet_name) worksheet_data.write_row(0, 1, years) worksheet_data.write_column(1, 0, row_names) workbook.close() return response # 表单校验失败返回表单页 return render(request, 'my_app/create_template.html', {'form':form})
3. my_app/urls.py 无需修改,原有配置可正常使用
内容的提问来源于stack exchange,提问作者project.py
相关产品推荐
相关产品推荐

