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

Django实现带页眉页脚的PDF下载(Reportlab)技术求助

嘿,刚接触Django就能想到用ReportLab生成PDF已经很棒了!直接用Canvas确实不太好处理页眉页脚,不过ReportLab的PageTemplate和Frame可以完美解决这个问题,下面给你一段完整的视图代码,拿过去就能用:

完整的Django视图代码

from django.http import HttpResponse
from reportlab.lib.pagesizes import letter
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, PageTemplate, Frame
from reportlab.lib.units import inch

def header_footer(canvas, doc):
    # 保存当前画布状态,避免后续操作影响全局
    canvas.saveState()
    styles = getSampleStyleSheet()
    
    # 绘制页眉:用Paragraph渲染富文本,也可以用canvas.drawString直接写纯文本
    header_content = Paragraph("我的自定义PDF页眉", styles["Heading2"])
    # 计算页眉宽高,定位到页面顶部(预留顶部边距)
    header_w, header_h = header_content.wrap(doc.width, doc.topMargin)
    header_content.drawOn(canvas, doc.leftMargin, doc.height + doc.topMargin - header_h)
    
    # 绘制页脚:加入动态页码
    footer_content = Paragraph(f"第 {doc.page} 页", styles["BodyText"])
    # 定位到页面底部(预留底部边距)
    footer_w, footer_h = footer_content.wrap(doc.width, doc.bottomMargin)
    footer_content.drawOn(canvas, doc.leftMargin, footer_h)
    
    # 恢复画布状态
    canvas.restoreState()

def download_pdf_with_header_footer(request):
    # 初始化HTTP响应,指定内容类型为PDF
    response = HttpResponse(content_type='application/pdf')
    # 设置响应头触发下载行为,自定义文件名
    response['Content-Disposition'] = 'attachment; filename="custom_pdf.pdf"'
    
    # 创建PDF文档对象,绑定到响应的输出流
    doc = SimpleDocTemplate(
        response,
        pagesize=letter,
        leftMargin=inch,
        rightMargin=inch,
        topMargin=inch,
        bottomMargin=inch
    )
    
    # 定义主内容区域的Frame:预留页眉页脚空间,避免内容重叠
    main_content_frame = Frame(
        doc.leftMargin,
        doc.bottomMargin + 0.5*inch,  # 页脚占0.5英寸高度
        doc.width,
        doc.height - 1*inch,  # 页眉+页脚共占1英寸高度
        id='main'
    )
    
    # 绑定页面模板和页眉页脚函数:每一页渲染时都会自动调用header_footer
    doc.addPageTemplates([
        PageTemplate(id='normal', frames=[main_content_frame], onPage=header_footer)
    ])
    
    # 准备PDF主体内容(可替换成你的业务内容)
    styles = getSampleStyleSheet()
    pdf_content = []
    pdf_content.append(Paragraph("PDF主标题", styles["Heading1"]))
    pdf_content.append(Spacer(1, 0.5*inch))
    # 模拟多段内容,测试自动分页时页眉页脚是否生效
    for i in range(15):
        pdf_content.append(
            Paragraph(
                f"第{i+1}段内容:Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
                styles["BodyText"]
            )
        )
        pdf_content.append(Spacer(1, 0.2*inch))
    
    # 构建并输出PDF
    doc.build(pdf_content)
    
    return response

关键细节说明

  • 页眉页脚函数:header_footer会在每一页渲染时被调用,doc.page可以获取当前页码;如果需要显示总页数,需要额外处理(因为总页数在文档完全构建后才会确定)
  • Frame布局:通过Frame精准定义主内容区域,把页眉页脚的空间单独预留出来,从根源避免内容和页眉页脚重叠
  • 响应头设置:Content-Disposition: attachment会让浏览器触发下载,若想在线预览可改成inline
  • 样式自定义:默认样式不够用的话,你可以用ParagraphStyle自行定义字体、颜色、对齐方式等

额外小技巧

如果需要在页眉里加Logo图片,可在header_footer函数中添加:

# 假设你的Logo存放在static/images/logo.png
from django.templatetags.static import static
canvas.drawImage(static('images/logo.png'), doc.leftMargin, doc.height + doc.topMargin - 0.5*inch, width=0.5*inch, height=0.5*inch)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:19:02