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
相关产品推荐
相关产品推荐

