---
title: "如何创建 PDF 文件"
version: 6.1
locale: zh-hans
source: https://docs.djangoproject.com/zh-hans/6.1/howto/outputting-pdf/
canonical: https://djangodocs.dev/zh-hans/6.1/howto/outputting-pdf/
---
# 如何创建 PDF 文件

本文介绍如何用 Django 的视图动态输出 PDF 文件。该功能由绝佳的开源 [ReportLab](https://docs.reportlab.com/) Python  PDF 库提供。

动态生成 PDF 文件的优点是你可以为不同的目的创建不同的自定义 PDF——例如，为不同的用户或内容的不同片段生成 PDF。

例如，[kusports.com](https://www2.kusports.com/) 用 Django 将自定义的，打印友好的 NCAA 锦标赛树状图生成 PDF 文件，发放给参加三月疯狂竞赛的人。

## 安装 ReportLab

ReportLab 库可以在 [PyPI 上获取](https://pypi.org/project/reportlab/)。还可以下载 [用户指南](https://www.reportlab.com/docs/reportlab-userguide.pdf) （巧合的是，它是一个 PDF 文件）。你可以使用 `pip` 安装 ReportLab：

```console
$ python -m pip install reportlab
```

*Windows*

```doscon
...\> py -m pip install reportlab
```

通过在 Python 交互式解释器中导入它来测试您的安装：

```pycon
>>> import reportlab
```

若该命令未抛出任何错误，安装成功。

## 编写视图

利用 Django 动态生成 PDF 的关键是 ReportLab API 作用于类文件对象，而 Django 的 [`FileResponse`](/zh-hans/6.1/ref/request-response/#django.http.FileResponse) 对象接收类文件对象。

这有个 "Hello World" 示例:

```
import io
from django.http import FileResponse
from reportlab.pdfgen import canvas

def some_view(request):
    # Create a file-like buffer to receive PDF data.
    buffer = io.BytesIO()

    # Create the PDF object, using the buffer as its "file."
    p = canvas.Canvas(buffer)

    # Draw things on the PDF. Here's where the PDF generation happens.
    # See the ReportLab documentation for the full list of functionality.
    p.drawString(100, 100, "Hello world.")

    # Close the PDF object cleanly, and we're done.
    p.showPage()
    p.save()

    # FileResponse sets the Content-Disposition header so that browsers
    # present the option to save the file.
    buffer.seek(0)
    return FileResponse(buffer, as_attachment=True, filename="hello.pdf")
```

代码和注释应该是不言自明的，但是有几件事值得提一下：

- 响应会自动基于文件扩展名将 MIME 类型设置为应用程序 `application/pdf`。这告诉浏览器该文档是个 PDF 文件，而不是 HTML 文件或普通的应用程序 `application/octet-stream` 二进制内容。
- 当将 `as_attachment=True` 传递给 `FileResponse` 时，它会设置适当的 `Content-Disposition` 标头，这会告诉 Web 浏览器弹出一个对话框，提示/确认如何处理文档，即使在计算机上设置了默认程序也是如此。如果省略了 `as_attachment` 参数，浏览器将使用它们配置为处理 PDF 的任何程序/插件来处理 PDF。
- 你也可以提供可选参数 `filename`。浏览器的“另存为…”对话框会用到它。
- 你可以作为第一个参数传递给 `canvas.Canvas` 的缓冲区也能传递给类 [`FileResponse`](/zh-hans/6.1/ref/request-response/#django.http.FileResponse) 类来使用 ReportLab API。
- 注意，所有后续生成 PDF 的方法都是在 PDF 对象上调用的（本例中是 `p`）——而不是在 `buffer` 上调用。
- 最后，牢记在 PDF 文件上调用 `showPage()` 和 `save()`。

> **Note**
>
> ReportLab 不是线程安全的。某些用户已经报告了一些奇怪的 issue，在创建用于生成 PDF 的 Django 视图时，这些视图被多个用户同时访问会出现问题。

## 其它格式

注意，这些例子中没有任何 PDF 特有的数据——只有使用 `reportlab` 的部分。你可以用类似的技巧生成任意格式，只要你能找到对应的 Python 库。也请看看 [如何输出 CSV](/zh-hans/6.1/howto/outputting-csv/)，看看另一个例子中，如何用一些技巧输出文本内容。

> **See also**
>
> Django 包提供了一个 [包的比较](https://djangopackages.org/grids/g/pdf/) 有助于用 Django 生成 PDF 文件。
