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

Django生成PDF时错误查找字体路径?出现TTFError报错

解决Django+xhtml2pdf渲染PDF时西里尔字体加载路径错误问题

问题根源

你的代码存在以下几个关键问题:

  1. fetch_resources函数中媒体资源路径处理错误(误用STATIC_ROOT代替MEDIA_ROOT)
  2. 硬编码静态资源URL导致路径解析异常
  3. 静态文件未正确收集到STATIC_ROOT目录
  4. HTML未指定UTF-8编码传递给PDF生成器

分步解决方案

1. 修正资源路径处理函数

更新fetch_resources函数,修复路径逻辑并增加文件存在验证:

import os
from django.conf import settings

def fetch_resources(uri, rel):
    # 处理静态文件
    if settings.STATIC_URL and uri.startswith(settings.STATIC_URL):
        path = os.path.join(settings.STATIC_ROOT, uri.replace(settings.STATIC_URL, ""))
    # 处理媒体文件(修正为MEDIA_ROOT)
    elif settings.MEDIA_URL and uri.startswith(settings.MEDIA_URL):
        path = os.path.join(settings.MEDIA_ROOT, uri.replace(settings.MEDIA_URL, ""))
    else:
        return uri

    # 转换为绝对路径并验证文件存在
    path = os.path.abspath(path)
    return path if os.path.exists(path) else uri

2. 修正PDF渲染函数的编码处理

确保HTML以UTF-8编码传递,避免西里尔字符乱码或解析错误:

from django.template.loader import get_template
from django.http import HttpResponse
from io import BytesIO
import xhtml2pdf.pisa as pisa

def render_pdf(url_template, context={}):
    template = get_template(url_template)
    html = template.render(context)
    result = BytesIO()
    # 指定UTF-8编码处理西里尔字符
    pdf = pisa.CreatePDF(BytesIO(html.encode("UTF-8")), result, link_callback=fetch_resources)
    if not pdf.err:
        return HttpResponse(result.getvalue(), content_type="application/pdf")
    return None

3. 调整模板中的字体引用

使用Django静态文件标签替代硬编码URL,确保路径正确生成:

{% load static %}
{% block extra_style %}
    <style type="text/css">
        @font-face { 
            font-family: Calibri; 
            src: url("{% static 'fonts/Calibri.ttf' %}"); 
            font-display: swap;
        }
        body { font-family: 'Calibri', sans-serif; }
    </style>
{% endblock %}

{% block content %}
    <body>
        <p>йоу</p>
    </body>
{% endblock %}

4. 收集静态文件到STATIC_ROOT目录

运行以下命令,将STATICFILES_DIRS中的资源复制到STATIC_ROOT:

python manage.py collectstatic

执行后确认D:\你的项目路径\static\fonts\Calibri.ttf文件存在。

5. 完善视图错误处理

避免返回空值导致的异常:

from django.views.generic import View

class DownloadPDF(View):
    def get(self, request, *args, **kwargs):
        pdf = render_pdf("tmp.html")
        if pdf:
            return pdf
        return HttpResponse("PDF生成失败", status=500)

额外检查项

  • 确保运行Django服务器的用户对STATIC_ROOT/fonts目录有读取权限
  • 检查系统临时目录(C:\Users\slavk\AppData\Local\Temp)的读写权限,必要时更换临时目录

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 09:58:08