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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 14:25:18