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

基于Django与ReportLab实现PDF渲染及打印功能的技术问询

我来帮你一步步实现每条记录旁的PDF打印按钮功能,核心思路是让PDF生成视图能针对单条记录生成专属内容,再给每条记录添加触发按钮,最后实现PDF加载后自动打印的效果。

步骤1:改造PDF生成视图,支持单条记录

你原来的PDF视图是固定文本,现在要改成接收记录ID,从数据库拉取对应记录并填充到PDF里。这里我用get_object_or_404简化不存在记录的处理:

from django.http import HttpResponse
from django.shortcuts import get_object_or_404
from io import BytesIO
from reportlab.pdfgen import canvas
from reportlab.lib.units import mm
from . import models

def record_pdf_view(request, record_id):
    # 获取指定ID的记录,不存在则返回404
    record = get_object_or_404(models.record, pk=record_id)
    
    # 初始化PDF响应,设置为浏览器内打开(inline)而非下载
    response = HttpResponse(content_type='application/pdf')
    response['Content-Disposition'] = f'inline; filename="record_{record_id}.pdf"'
    
    buffer = BytesIO()
    my_canvas = canvas.Canvas(buffer)
    
    # 开始写入PDF内容,替换成你实际的record模型字段
    textobject = my_canvas.beginText(30 * mm, 65 * mm)
    textobject.setFont('Times-Roman', 10)
    textobject.textLine(f"患者姓名: {record.patient_assign.name}")
    textobject.textLine(f"记录日期: {record.date.strftime('%Y-%m-%d %H:%M')}")
    textobject.textLine("----------------------------")
    textobject.textLine(f"记录内容: {record.content}")
    # 可以继续添加更多字段,比如诊断结果、医生姓名等
    
    my_canvas.drawText(textobject)
    my_canvas.setTitle(f"患者记录 #{record_id}")
    my_canvas.showPage()
    my_canvas.save()
    
    pdf = buffer.getvalue()
    buffer.close()
    response.write(pdf)
    return response
步骤2:配置URL路由

在你的app的urls.py里,新增PDF视图的路由,方便模板反向解析:

from django.urls import path
from . import views

urlpatterns = [
    # 保留你原有的患者页面路由
    path('patient/<int:id>/', views.patient_page, name='patient_page'),
    # 新增单条记录的PDF路由
    path('record/pdf/<int:record_id>/', views.record_pdf_view, name='record_pdf'),
]
步骤3:在HTML模板添加打印按钮

在patient_page.html的记录循环里,给每条记录加按钮。这里提供两种方案:

方案1:简单链接按钮(手动打印)

点击后在新窗口打开PDF,用户手动点击浏览器打印按钮:

{% for record in rec %}
    <div class="record-card">
        <h4>记录日期: {{ record.date|date:"Y-m-d H:i" }}</h4>
        <p>{{ record.content }}</p>
        <!-- 用url标签反向生成PDF链接,传递当前记录ID -->
        <a href="{% url 'record_pdf' record.id %}" target="_blank" class="btn btn-primary">打印这条记录</a>
    </div>
{% endfor %}

方案2:自动触发打印(更友好)

用JS创建隐藏iframe加载PDF,加载完成后自动弹出打印对话框:

{% for record in rec %}
    <div class="record-card">
        <h4>记录日期: {{ record.date|date:"Y-m-d H:i" }}</h4>
        <p>{{ record.content }}</p>
        <button onclick="printSingleRecord({{ record.id }})" class="btn btn-primary">打印这条记录</button>
    </div>
{% endfor %}

<script>
function printSingleRecord(recordId) {
    // 创建隐藏iframe加载PDF
    const iframe = document.createElement('iframe');
    iframe.style.display = 'none';
    // 替换URL中的占位符为实际记录ID
    iframe.src = "{% url 'record_pdf' 0 %}".replace('0', recordId);
    document.body.appendChild(iframe);

    // 等待PDF加载完成后触发打印
    iframe.onload = function() {
        try {
            iframe.contentWindow.print();
            // 打印完成后移除iframe
            setTimeout(() => document.body.removeChild(iframe), 1500);
        } catch (e) {
            // 若自动打印失败(浏览器安全限制),则打开新窗口让用户手动操作
            window.open(iframe.src, '_blank');
            document.body.removeChild(iframe);
        }
    };
}
</script>
额外提示
  • 记得根据你实际的record模型字段调整PDF里的内容,比如如果有diagnosis(诊断)、doctor(医生)字段,直接添加对应的textobject.textLine即可。
  • 如果需要更复杂的PDF样式(比如表格、页眉页脚),可以参考ReportLab的官方文档扩展功能,比如用SimpleDocTemplate代替canvas来构建结构化文档。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:10:46