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

如何使用Django模板生成带有完整CSS样式的PDF文件?

Django模板生成带CSS样式的PDF解决方案

你当前用xhtml2pdf生成PDF时内容正常但CSS不生效,核心原因是xhtml2pdf对CSS的支持逻辑和浏览器不同,且外部资源加载存在局限,以下是具体解决步骤:

1. 优先使用内嵌CSS,避免外部样式文件

xhtml2pdf加载外部CSS文件容易出现路径解析问题,建议直接把CSS写在模板的<style>标签内,或给元素添加style属性。示例模板abc.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>PDF示例</title>
    <style type="text/css">
        .page-container {
            width: 210mm;
            margin: 0 auto;
            padding: 15mm;
        }
        .header {
            color: #3498db;
            font-size: 22px;
            text-align: center;
            border-bottom: 2px solid #eee;
            padding-bottom: 10px;
        }
        .content-text {
            font-size: 14px;
            line-height: 1.8;
            margin-top: 20px;
            color: #333;
        }
    </style>
</head>
<body>
    <div class="page-container">
        <h2 class="header">带样式的PDF标题</h2>
        <p class="content-text">这是应用了CSS样式的PDF内容,测试段落。</p>
    </div>
</body>
</html>

2. 修改PDF生成函数,添加资源回调

xhtml2pdf需要明确的资源路径才能加载静态文件(如字体、图片),给pisaDocument添加link_callback参数处理路径转换:

from io import BytesIO
from xhtml2pdf import pisa
from django.template.loader import get_template
from django.http import HttpResponse
from django.conf import settings
import os

def home(request):
    pdf = render_to_pdf("abc.html")
    return HttpResponse(pdf, content_type='application/pdf')

def link_callback(uri, rel):
    # 处理静态文件和媒体文件路径
    if uri.startswith(settings.STATIC_URL):
        path = os.path.join(settings.STATIC_ROOT, uri.replace(settings.STATIC_URL, ""))
    elif uri.startswith(settings.MEDIA_URL):
        path = os.path.join(settings.MEDIA_ROOT, uri.replace(settings.MEDIA_URL, ""))
    else:
        return uri  # 外部资源直接返回原地址
    
    # 校验文件是否存在
    if not os.path.isfile(path):
        raise FileNotFoundError(f"静态资源未找到: {path}")
    return path

def render_to_pdf(template_src, context_dict={}):
    template = get_template(template_src)
    html = template.render(context_dict)
    result = BytesIO()
    # 配置pisa文档,添加回调并改用UTF-8编码避免乱码
    pdf = pisa.pisaDocument(
        BytesIO(html.encode("UTF-8")),
        result,
        link_callback=link_callback
    )
    if not pdf.err:
        return HttpResponse(result.getvalue(), content_type='application/pdf')
    else:
        return None

3. 注意xhtml2pdf的CSS支持局限

xhtml2pdf基于ReportLab,对CSS的支持不如浏览器完善,需规避以下特性:

  • 避免使用float、flex等复杂布局,优先用<table>实现排版
  • 伪类(如:hover、:nth-child)、多层嵌套的后代选择器基本不支持
  • 自定义字体需通过@font-face引入,且要确保字体文件路径正确(配合上述link_callback)

4. 中文显示与字体配置

如果需要显示中文,需引入支持中文的字体(如宋体、微软雅黑),示例:
在静态目录static/fonts/下放入SimSun.ttf字体文件,然后在模板的<style>中添加:

@font-face {
    font-family: 'SimSun';
    src: url('{% static "fonts/SimSun.ttf" %}') format('truetype');
}
body {
    font-family: 'SimSun', serif;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 16:36:10