Django使用reportlab套件生成PDF文件
2018-04-20 13:39
507 查看
简介
项目中生成了一个实例,需要提供给用户下载pdf文件功能。最开始想到的是使用前段技术,直接将html页面保存为pdf文件。这个过程使用了html2pdf,这个纯js项目。该项目会将指定的DOM元素通过html2canvas工具保存为图片,然后通过jsPDF工具将保存的图片最终以pdf文件形式展现,并直接供下载。
这样做有个缺点就是当页面非常长时,就有可能出现一行文字被从中间截断,展示在两页pdf文件中的情况。因而需要寻找更高级,输出格式更优雅的解决方案。最后发现了可以通过Reportlab套件来完成工作。
工作流
要想通过Reportlab套件来生成pdf文件的工作流程主要分三步:django后台通过与数据库或者其他调用获取数据
将这些数据传入到RML(Report Markable Language)模板,并调用reportlab套件生成二进制数据
django根据生成的数据返回响应
第1和第3步可以参考官方outputting pdf文档
比较关键的是第2步如何实现,下面将针对RML、以及如何调用reportlab套件生成二进制数据进行详细讲解
RML和Reportlab套件使用
关于RML可以参考Reportlab提供的RML-for-Idiots和RML User Guide两个文档进行学习,这里并不赘述。只介绍个人使用的一些体会。首页与其余页使用不同模板
要想实现第一页和后面其余页使用不同的模板,在
<story>上添加
firstPageTemplate属性,指定第一页的模板。紧接着使用
<setNextTempate name='main'>来指定剩余页(如果有的话)使用的模板。
如果想整个pdf使用同一个模板的话,则无须使用
<setNextTempate name='main'>。
<?xml version="1.0" encoding="utf-8" standalone="no" ?> <!DOCTYPE document SYSTEM "rml_1_0.dtd"> <document filename="rml.pdf"> <template pagesize="(595, 842)" leftMargin="72"> <pageTemplate id="head"> <pageGraphics> <setFont name="bighei" size="24"/> <drawCentredString x="297.5" y="760">{{ name }}</drawCentredString> </pageGraphics> <frame id="first" x1="80" y1="80" width="435" height="550"/> </pageTemplate> <pageTemplate id="main"> <frame id="first" x1="80" y1="80" width="435" height="682"/> </pageTemplate> </template> <stylesheet> <initialize> <alias id="style.normal" value="style.Normal"/> </initialize> <paraStyle name="chapter title" fontName="bighei" fontSize="20" leading="36" spaceAfter="10"/> <paraStyle name="question stem" fontName="bighei" fontSize="12" leading="12" spaceBefore="15" spaceAfter="10"/> <paraStyle name="question options" fontName="bighei" fontSize="10" leading="12" spaceAfter="5" /> </stylesheet> <story firstPageTemplate="head"> <setNextTemplate name="main" /> {{ paras }} </story> </document>
通过Django template解决RML不能嵌套循环问题
个人在使用过程中发现无法在RML模板中进行嵌套循环,
{{ for outter_item in outter_list }} {{ for inner_item in outter_item }} {{ innger_item }} {{ endfor }} {{ endfor }}
但是Django模板中并无此限制,因而可以直接调用
render_to_string方法将RML需要的字符串使用django的机制来生成,然后再传给RML解决这个问题。
from io import BytesIO import preppy import trml2pdf TEMPLATE = os.path.join(PATH_TO_TEMPLATE_DIR, 'template.prep') def generate_pdf(): django_context = dict() paras = render_to_string('django_templates.html', django_context) rml_context = dict( name='RML Test', paras=paras.encode("utf-8") ) template = preppy.getModule(template_path) rml = template.getOutput(rml_context) return trml2pdf.parseString(rml)
解决中文乱码问题
RML默认不支持中文,需要自己注册支持中文的字体
from reportlab.pdfbase import pdfmetrics from reportlab.pdfbase import ttfonts pdfmetrics.registerFont(ttfonts.TTFont(font_name, font_path))
Django views
def test_rml(request): response = HttpResponse(content_type='application/pdf') response['Content-Disposition'] = 'attachment; filename="rml.pdf"' pdf = generate_pdf() response.write(pdf) return response
相关文章推荐
- django生成文件txt、pdf(在生成 PDF 文件之前,需要安装 ReportLab 库)
- itext使用模板生成pdf文件
- 使用Aspose.Pdf处理XML文档生成PDF文件
- 使用的开放源码Scryber库动态生成PDF文件
- java使用IText生成PDF格式文件
- C#——使用iTextSharp生成pdf文件
- C#使用itextsharp生成PDF文件
- 生成PDF文件-使用iText制作复杂表格
- 滴水穿石--Java 生成PDF文件--iText使用之插入图片和中文乱码
- fpdf 在php中生成pdf文件时如何使用自定义字库.
- 使用office生成PDF文件
- VBA使用Acrobat Distiller生成PDF文件
- WinEdt7生成PDF文件中的一些使用体会
- 使用reportlab生成中文表格pdf
- 使用ireport做pdf报表,生成的pdf一直都是文件损坏,无法打开,哪位大侠指点一下
- 使用Apache XML项目FOP生成PDF文件(上)
- 在Ubuntu系统使用Texlive生成PDF文件命令
- C#——使用iTextSharp生成pdf文件
- C#使用itextsharp生成PDF文件
- PDF文件的读写(使用SDK).(二).编译生成免费的PoDoFo