Django 如何使用视图动态输出 CSV 以及 PDF
这一篇我们需要用到 python
的 csv
和 reportLab
库,通过django视图来定义输出我们需要的 csv
或者 pdf
文件。
一、csv文件
打开我们的视图文件 testsite/members/views.py
。新增一个视图方法:
1 2 3 4 5 6 7 8 9 10 11 | 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
,添加一个路由:
1 | 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
文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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
文件:
1 | 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
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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
文件:
1 | path( 'csv-template/' , views.some_view_tem, name = 'csv' ), |
在当前目录下面的 templates
文件夹创建我们的模板文件 my_template_name.txt
:
1 2 | { % 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 库:
1 | py -m pip install reportlab |
我们可以看到下列结果:
使用 django
动态生成 pdf
的关键在于 ReportLab API
作用于类似文件的对象,而 Django
的FileResponse
对象接受类似文件的对象。
打开我们的 testsite/members/views.py
视图文件:
1 2 3 4 5 6 7 8 9 10 11 | 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
文件:
1 | 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的资料请关注IT俱乐部其它相关文章!