Django如何在主视图直接触发PDF导出以复用数据处理代码?
如何在主视图中直接处理PDF导出并避免代码重复?
当然可以实现,核心思路是在主视图里根据请求参数分支处理:正常请求返回网页,带导出参数的请求返回PDF,这样那300行数据处理代码只需要写一次,完全不用复制到其他视图。
步骤1:修改主视图,添加PDF导出逻辑
直接在dispatcher_single视图中加入PDF导出的分支判断,复用已有的数据处理逻辑:
# views.py from renderers import render_to_pdf from django.http import Http404 def dispatcher_single(request, pk): dispatcher = Dispatcher.objects.select_related("company", "location").get(id=pk) # 这里是你的300行数据处理代码,只执行一次 # ... 数据计算、图表生成相关逻辑 ... context = { 'dispatcher': dispatcher, 'bunch_of_other_data': data } # 判断是否触发PDF导出 if request.GET.get('export') == 'pdf': # 调用PDF渲染函数,传入PDF专用模板和已准备好的上下文 response = render_to_pdf("pdf/dispatcher-statement.html", context) if response.status_code == 404: raise Http404("PDF模板未找到") # 设置PDF文件名和展示方式 filename = f"{dispatcher.name}_报表.pdf" content_disposition = f"inline; filename={filename}" # 如果带download参数,改为下载模式 if request.GET.get('download'): content_disposition = f"attachment; filename={filename}" response["Content-Disposition"] = content_disposition return response # 默认返回网页视图 return render(request, 'dispatchers/dispatcher-single.html', context)
步骤2:在模板中添加导出按钮
在主页面模板dispatcher-single.html里添加触发导出的按钮,指向当前视图并带上导出参数:
<!-- dispatchers/dispatcher-single.html --> <div class="export-buttons"> <a href="{% url 'dispatcher_single' pk=dispatcher.id %}?export=pdf" class="btn btn-primary">在线预览PDF</a> <a href="{% url 'dispatcher_single' pk=dispatcher.id %}?export=pdf&download=1" class="btn btn-secondary">下载PDF报表</a> </div>
步骤3:准备PDF专用模板
创建pdf/dispatcher-statement.html模板,你可以复用主模板中的数据展示部分(比如表格、图表的HTML结构),只需要调整样式适配PDF渲染(比如移除导航栏、调整字体大小、确保内容在PDF页面范围内)。
保留原有的PDF渲染函数
你的renderers.py可以继续使用,只需添加中文注释更清晰:
# renderers.py from django.template.loader import get_template from django.http import HttpResponse from io import BytesIO from xhtml2pdf import pisa def render_to_pdf(template_src, context_dict={}): # 加载指定的HTML模板 template = get_template(template_src) # 用上下文数据渲染模板生成HTML内容 html = template.render(context_dict) # 创建字节流对象用于存储生成的PDF result = BytesIO() # 将HTML内容转换为PDF pdf = pisa.pisaDocument(BytesIO(html.encode("ISO-8859-1")), result) # 如果转换过程出错,返回错误响应 if pdf.err: return HttpResponse("无效的PDF内容", status_code=400, content_type='text/plain') # 返回生成的PDF文件响应 return HttpResponse(result.getvalue(), content_type='application/pdf')
这样修改后,用户点击按钮时会触发同一个视图,复用所有数据处理逻辑,直接生成PDF,完全避免了代码复制。
内容的提问来源于stack exchange,提问作者Valeriu
相关产品推荐
相关产品推荐

