django 如何使用视图动态输出 csv 以及 pdf
这一篇我们需要用到 python 的 csv 和 reportlab 库,通过django视图来定义输出我们需要的 csv 或者 pdf 文件。
一、csv文件
打开我们的视图文件 testsite/members/views.py 。新增一个视图方法:
import csv # 导入python的csv包
def some_view(request):
# create the httpresponse object with the appropriate csv header.
response = httpresponse(
content_type="text/csv",
headers={"content-disposition": 'attachment; filename="somefilename.csv"'},
)
writer = csv.writer(response)
writer.writerow(["第一行", "foo", "bar", "baz"])
writer.writerow(["第二行", "a", "b", "c", '"testing"', "here's a quote"])
return response
在上面代码里面
- 响应会获得一个特殊的
mime类型text/csv。会告诉浏览器该文档是一个csv文件,而不是html文件。 - 响应会获得一个附加
content-disposition标头,其中包含csv文件的名称。此文件名是任意的;您可以随意命名。浏览器会在“另存为…”对话框中使用它。 response您可以通过将作为第一个参数传递给 来挂接csv生成api csv.writer。该csv.writer函数需要一个类似文件的对象,并且httpresponse对象符合要求。- 对于
csv文件中的每一行,调用writer.writerow,并将一个 可迭代的传递给它。 csv模块会为您处理引号,因此您不必担心转义带引号或逗号的字符串。传递writerow()您的原始字符串,它会做正确的事情。
然后打开我们的路由文件 testsite/members/urls.py ,添加一个路由:
path('csv/', views.some_view, name='csv'),
访问我们的 http://127.0.0.1:8000/members/csv 地址,可以得到一个 csv 文件。如下图所示:

打开文件里面就是我们自定义格式的 csv 。

如果当我们在使用流式传输大型 csv 文件的时候,在处理生成非常大响应的视图时,就要改用 django streaminghttpresponse 为啥要改成这个呢
举个例子,通过流式传输需要很长时间才能生成的文件,您可以避免负载平衡器在服务器生成响应时丢弃可能超时的连接。
在下面例子中,我们就可以充分利用 python 生成器来高效处理大型 csv 文件的组装和传输,打开 testsite/members/views.py 文件:
import csv
from django.http import streaminghttpresponse
class echo:
"""an object that implements just the write method of the file-like
interface.
"""
def write(self, value):
"""write the value by returning it, instead of storing in a buffer."""
return value
def some_streaming_csv_view(request):
"""a view that streams a large csv file."""
rows = (["row {}".format(idx), str(idx)] for idx in range(65536))
pseudo_buffer = echo()
writer = csv.writer(pseudo_buffer)
return streaminghttpresponse(
(writer.writerow(row) for row in rows),
content_type="text/csv",
headers={"content-disposition": 'attachment; filename="somefilename.csv"'},
)
添加我们的路由,打开我们的 testsite/members/urls.py 文件:
path('csv-stream/', views.some_streaming_csv_view, name='csv'),
浏览器访问 http://127.0.0.1:8080/members/csv-stream 流式输出文件:

打开这个文件如图示:

当然还一种方式来生成 csv ,通过 django 的模版系统。下面跟着代码来试一下这种方法:
依然还是先打开视图文件 testsite/members/views.py :
from django.http import httpresponse
from django.template import loader
def some_view(request):
response = httpresponse(
content_type="text/csv",
headers={"content-disposition": 'attachment; filename="somefilename.csv"'},
)
csv_data = (
("first row", "foo", "bar", "baz"),
("second row", "a", "b", "c", '"testing"', "here's a quote"),
)
t = loader.get_template("my_template_name.txt")
c = {"data": csv_data}
response.write(t.render(c))
return response
添加我们的路由,打开我们的 testsite/members/urls.py 文件:
path('csv-template/', views.some_view_tem, name='csv'),
在当前目录下面的 templates 文件夹创建我们的模板文件 my_template_name.txt :
{% for row in data %}"{{ row.0|addslashes }}", "{{ row.1|addslashes }}", "{{ row.2|addslashes }}", "{{ row.3|addslashes }}", "{{ row.4|addslashes }}"
{% endfor %}
浏览器访问 http://127.0.0.1:8080/members/csv-template 流式输出文件:

就可以得到我们自定义模板的 csv 文件。
二、如何创建 pdf 文件
由于 python 拥有出色的开源 reportlab python pdf 库,使得我们动态生成 pdf 非常有优势。
首先我们安装reportlab 库:
py -m pip install reportlab
我们可以看到下列结果:

使用 django 动态生成 pdf 的关键在于 reportlab api 作用于类似文件的对象,而 django 的fileresponse 对象接受类似文件的对象。
打开我们的 testsite/members/views.py 视图文件:
import io
from django.http import fileresponse
from reportlab.pdfgen import canvas
def some_view_pdf(request):
buffer = io.bytesio()
p = canvas.canvas(buffer)
p.drawstring(100, 100, "hello world.")
p.showpage()
p.save()
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标头,并告诉网络浏览器弹出一个对话框,提示/确认如何处理文档,即使机器上设置了默认值。如果as_attachment省略该参数,浏览器将使用已配置用于pdf的任何程序/插件来处理pdf。 filename定义你需要输出的pdf名字。浏览器将在“另存为…”对话框中使用它。- 可以挂接到
reportlab api:作为第一个参数传递的相同缓冲区canvas.canvas可以提供给该类fileresponse。 - 所有后面的
pdf生成方法均在pdf对象(上面例子中为p)上调用,而不是在 上调用buffer。 showpage()最后,调用并save()查看pdf文件非常重要。
添加我们的路由,打开我们的 testsite/members/urls.py 文件:
path('csv-stream/', views.some_streaming_csv_view, name='csv'),
浏览器访问 http://127.0.0.1:8080/members/pdf:

打开 pdf 文件,就可以看到我们自动输出的 pdf 文件:

reportlab 并不是线程安全的。
所以一些小伙伴在构建 pdf 生成 django 视图时出现的奇怪问题,这些视图就是由于许多人同时访问造成的。
三、总结
虽然 csv 文件和 pdf 文件的动态生成技术很常见,也是业务中经常用到的,我们文中所用到的只是其中的某个包,比如 reportlab 。
在 django 官方的 packages 有更详细不同包的比较,以及他们的使用方式,https://djangopackages.org/grids/g/pdf/。
利用这两个工具结合我们的 django 视图,就完全的能和我们自己开发的系统结合起来了。
根据相应的显示字段动态生成一切我们想要的文件,是非常方便的。
以上就是django使用视图动态输出csv以及pdf的操作详解的详细内容,更多关于django视图输出csv及pdf的资料请关注代码网其它相关文章!
发表评论