Django生成PDF并解决中文乱码:基于xhtml2pdf的完整实现

慢慢来
慢慢来
发布时间:2026-10-13 | 6人浏览过
原创

本文介绍如何在Django项目中利用xhtml2pdf库生成PDF文件,重点解决中文显示乱码问题。通过配置中文字体、编写表单验证与类视图,实现用户信息到PDF的转换。文章包含完整的安装步骤、代码示例及字体配置方法,帮助开发者快速实现PDF下载与预览功能。

项目源码已托管于GitHub:https://github.com/PythonerKK/django-generate-pdf/tree/master

该示例项目演示了如何根据用户输入的个人信息生成一份简历PDF,旨在说明使用Django的HttpResponse来创建和返回PDF文档的具体流程。

以下是最终效果的展示截图:

安装依赖库

环境依赖安装

首先,需要安装最新版本的Django(版本2.2.2)以及用于处理PDF生成的依赖包xhtml2pdf。


pip install django
pip install xhtml2pdf

编写表单验证

表单数据验证逻辑

为了简化演示,本项目依赖数据库存储,主要关注表单数据的验证环节。相关代码位于pdf/forms.py中。


class MessageForm(forms.Form):
  '''
  表单验证
  '''
  name = forms.CharField(required=True)
  degree = forms.CharField(required=True)
  edu = forms.CharField(required=True)
  work = forms.CharField(required=True)
  tech = forms.CharField(required=True)
  phone = forms.CharField(required=True)

编写类视图

类视图开发

具体视图逻辑见pdf/views.py。由于本例仅需处理表单视图,因此仅定义了一个类视图。其中post方法用于验证表单数据是否完整,若验证通过,则将表单数据渲染至PDF模板,经处理后返回PDF响应对象。

此处也可选用Django的通用类视图FormView来构建,可使代码结构更为简洁。


class MessageView(View):
  def get(self, request):
    form = MessageForm(data=request.GET)
    return render(request, 'index.html', {
      'form': form
    })

  def post(self, request):
    form = MessageForm(data=request.POST)
    if form.is_valid():
      response = generate_pdf_response(context=form.cleaned_data)
      return response
    return redirect(reverse('pdf:message'))

生成PDF响应

生成PDF响应对象

相关实现代码见view.py。为便于理解,处理函数直接编写在视图文件内。


def link_callback(uri):
  if uri.startswith(settings.MEDIA_URL):
    path = os.path.join(settings.MEDIA_ROOT,
              uri.replace(settings.MEDIA_URL, ""))
  elif uri.startswith(settings.STATIC_URL):
    path = os.path.join(settings.STATIC_ROOT,
              uri.replace(settings.STATIC_URL, ""))
  else:
    return uri

  # 确保本地文件存在
  if not os.path.isfile(path):
    raise Exception(
      "Media URI 必须以以下格式开头"
      f"'{settings.MEDIA_URL}' or '{settings.STATIC_URL}'")

  return path


def generate_pdf_response(context):
  response = HttpResponse(content_type="application/pdf")
  response["Content-Disposition"] = \
    f"attachment; filename='{context['name']}.pdf'"

  html = render_to_string("pdf.html", context=context)
  status = pisa.CreatePDF(html,
              dest=response,
              link_callback=link_callback)

  if status.err:
    return HttpResponse("PDF文件生成失败")
  return response

解决中文乱码问题

中文乱码问题处理

需下载中文字体文件msyh.ttf,并将其放置于static目录下的font文件夹中,以便设置全局字体。这些资源文件均包含在GitHub仓库内。


def font_patch():
  from reportlab.pdfbase.ttfonts import TTFont
  from reportlab.pdfbase import pdfmetrics
  from xhtml2pdf.default import DEFAULT_FONT
  pdfmetrics.registerFont(TTFont('yh', '{}/font/msyh.ttf'.format(
    settings.STATICFILES_DIRS[0])))
  DEFAULT_FONT['helvetica'] = 'yh'

该字体配置函数应置于生成PDF响应的逻辑之前执行。

遵循上述步骤,即可成功生成PDF文件。用户可在网页中直接浏览、放大或缩小查看,亦支持下载,操作便捷。欢迎克隆代码进行实际测试。

项目源码地址:https://github.com/PythonerKK/django-generate-pdf/tree/master

以上内容为本文全部介绍,期望对读者的学习有所助益,同时也感谢大家的支持。

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表