Django项目:服务端将已渲染动态页面转PDF实现示例请求
在Django中将动态渲染页面转为PDF的服务端方案
刚好我在Django项目里处理过类似的需求——把服务端渲染的动态页面转成PDF,还得支持西里尔文,客户端方案确实踩过不少坑,给你分享几个靠谱的服务端实现方案:
方案一:WeasyPrint(推荐,纯Python,Unicode友好)
WeasyPrint是纯Python编写的PDF生成库,对现代CSS支持不错,原生支持Unicode(包括西里尔文),不需要额外安装二进制依赖,非常适合Django场景。
实现步骤:
- 安装依赖:
pip install weasyprint
- 编写Django视图函数:
先通过render_to_string把动态数据渲染成HTML字符串,再用WeasyPrint转换成PDF返回给客户端:
from django.template.loader import render_to_string from weasyprint import HTML from django.http import HttpResponse def dynamic_page_to_pdf(request): # 模拟你的动态数据(可以从数据库/API获取) context = { 'page_title': '我的动态PDF页面', 'welcome_text': 'Привет, мир!', # 西里尔文字符 'data_list': ['Первый элемент', 'Второй элемент', 'Третий элемент'] } # 渲染模板为HTML字符串 html_content = render_to_string('dynamic_pdf_template.html', context) # 生成PDF文件 pdf_file = HTML(string=html_content).write_pdf() # 构造响应,让浏览器下载PDF response = HttpResponse(pdf_file, content_type='application/pdf') response['Content-Disposition'] = 'attachment; filename="dynamic_content.pdf"' return response
- 编写对应的模板(
templates/dynamic_pdf_template.html):
关键是要使用支持西里尔文的字体,避免乱码:
<!DOCTYPE html> <html lang="ru"> <head> <meta charset="UTF-8"> <title>{{ page_title }}</title> <style> /* 使用支持西里尔文的字体,DejaVu Sans是免费且常用的选择 */ body { font-family: 'DejaVu Sans', sans-serif; padding: 20px; } .list-container { margin-top: 20px; } .list-item { margin: 8px 0; list-style-type: square; } </style> </head> <body> <h1>{{ welcome_text }}</h1> <div class="list-container"> <h3>动态数据列表:</h3> <ul> {% for item in data_list %} <li class="list-item">{{ item }}</li> {% endfor %} </ul> </div> </body> </html>
注意事项:
- 如果服务器上没有
DejaVu Sans字体,可以通过@font-face加载Web字体,或者在服务器上安装该字体 - WeasyPrint支持大部分CSS3特性,复杂样式也能很好渲染
方案二:xhtml2pdf(轻量,适合简单页面)
xhtml2pdf是另一个常用的Django PDF生成库,体积更小,适合结构简单的页面,同样支持Unicode字符。
实现步骤:
- 安装依赖:
pip install xhtml2pdf
- 编写视图函数:
from django.template.loader import render_to_string from xhtml2pdf import pisa from django.http import HttpResponse def generate_pdf(request): context = { 'title': 'xhtml2pdf动态示例', 'content': '西里尔文测试:Привет из xhtml2pdf!' } # 渲染HTML html_content = render_to_string('simple_pdf_template.html', context) # 构造响应 response = HttpResponse(content_type='application/pdf') response['Content-Disposition'] = 'attachment; filename="simple_output.pdf"' # 生成PDF,指定UTF-8编码 pisa_status = pisa.CreatePDF(html_content, dest=response, encoding='UTF-8') # 处理生成错误 if pisa_status.err: return HttpResponse(f'PDF生成失败: {pisa_status.err}') return response
- 模板中同样要指定支持西里尔文的字体,可以把字体文件放到静态目录,通过
@font-face引入:
@font-face { font-family: 'DejaVuSans'; src: url('{{ STATIC_URL }}fonts/DejaVuSans.ttf') format('truetype'); } body { font-family: DejaVuSans, sans-serif; }
方案三:wkhtmltopdf(适合复杂HTML/CSS)
如果你的动态页面包含复杂的CSS布局甚至少量JavaScript,wkhtmltopdf会更合适——它基于WebKit引擎,相当于把页面在浏览器中渲染后转成PDF,对HTML/CSS的支持几乎完美。
实现步骤:
- 安装wkhtmltopdf二进制文件:
- Ubuntu/Debian:
sudo apt-get install wkhtmltopdf - Windows:从官方渠道下载安装包并配置环境变量
- 安装Django集成库:
pip install django-wkhtmltopdf
- 编写视图:
from django.views.generic import View from wkhtmltopdf.views import PDFTemplateResponse class DynamicPDFView(View): def get(self, request): context = { 'dynamic_content': 'Привет, это由wkhtmltopdf生成的PDF!' } return PDFTemplateResponse( request=request, template='complex_pdf_template.html', filename='complex_dynamic.pdf', context=context, content_type='application/pdf' )
注意事项:
- 需要确保服务器上安装了wkhtmltopdf二进制,并且Django能找到它的路径(可以在settings.py中配置
WKHTMLTOPDF_CMD) - 对JavaScript渲染的内容支持也很好,如果你的页面有前端动态渲染的部分,这个方案更适合
总结
- 如果追求纯Python、无额外依赖,优先选WeasyPrint,足够应对大部分动态页面,西里尔文支持完美
- 页面结构简单、追求轻量,选xhtml2pdf
- 复杂布局/需要JS支持,选wkhtmltopdf
所有方案都需要注意使用支持西里尔文的字体,确保模板编码为UTF-8,这样就能避免乱码问题了。
内容的提问来源于stack exchange,提问作者Aleks Porberevskiy
相关产品推荐
相关产品推荐

