翼度科技»论坛 编程开发 python 查看内容

Django使用视图动态输出CSV以及PDF的操作详解

5

主题

5

帖子

15

积分

新手上路

Rank: 1

积分
15
Django 如何使用视图动态输出 CSV 以及 PDF

这一篇我们需要用到
  1. python
复制代码
  1. csv
复制代码
  1. reportLab
复制代码
库,通过django视图来定义输出我们需要的
  1. csv
复制代码
或者
  1. pdf
复制代码
文件。

一、csv文件

打开我们的视图文件
  1. testsite/members/views.py
复制代码
。新增一个视图方法:
  1. import csv  # 导入python的csv包
  2. def some_view(request):
  3.     # Create the HttpResponse object with the appropriate CSV header.
  4.     response = HttpResponse(
  5.         content_type="text/csv",
  6.         headers={"Content-Disposition": 'attachment; filename="somefilename.csv"'},
  7.     )
  8.     writer = csv.writer(response)
  9.     writer.writerow(["第一行", "Foo", "Bar", "Baz"])
  10.     writer.writerow(["第二行", "A", "B", "C", '"Testing"', "Here's a quote"])
  11.     return response
复制代码
在上面代码里面

  • 响应会获得一个特殊的
    1. MIME
    复制代码
    类型
    1. text/csv
    复制代码
    。会告诉浏览器该文档是一个
    1. CSV
    复制代码
    文件,而不是
    1. HTML
    复制代码
    文件。
  • 响应会获得一个附加
    1. Content-Disposition
    复制代码
    标头,其中包含
    1. CSV
    复制代码
    文件的名称。此文件名是任意的;您可以随意命名。浏览器会在“另存为…”对话框中使用它。
    1. response
    复制代码
    您可以通过将作为第一个参数传递给 来挂接
    1. CSV
    复制代码
    生成
    1. API csv.writer
    复制代码
    。该
    1. csv.writer
    复制代码
    函数需要一个类似文件的对象,并且
    1. HttpResponse
    复制代码
    对象符合要求。
  • 对于
    1. CSV
    复制代码
    文件中的每一行,调用
    1. writer.writerow
    复制代码
    ,并将一个 可迭代的传递给它。
    1. CSV
    复制代码
    模块会为您处理引号,因此您不必担心转义带引号或逗号的字符串。传递
    1. writerow()
    复制代码
    您的原始字符串,它会做正确的事情。
然后打开我们的路由文件
  1. testsite/members/urls.py
复制代码
,添加一个路由:
  1. path('csv/', views.some_view, name='csv'),
复制代码
访问我们的
  1. http://127.0.0.1:8000/members/csv
复制代码
地址,可以得到一个
  1. csv
复制代码
文件。如下图所示:

打开文件里面就是我们自定义格式的
  1. csv
复制代码


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

打开这个文件如图示:

当然还一种方式来生成
  1. csv
复制代码
,通过
  1. django
复制代码
的模版系统。下面跟着代码来试一下这种方法:
依然还是先打开视图文件
  1. testsite/members/views.py
复制代码
  1. from django.http import HttpResponse
  2. from django.template import loader
  3. def some_view(request):
  4.     response = HttpResponse(
  5.         content_type="text/csv",
  6.         headers={"Content-Disposition": 'attachment; filename="somefilename.csv"'},
  7.     )
  8.     csv_data = (
  9.         ("First row", "Foo", "Bar", "Baz"),
  10.         ("Second row", "A", "B", "C", '"Testing"', "Here's a quote"),
  11.     )
  12.     t = loader.get_template("my_template_name.txt")
  13.     c = {"data": csv_data}
  14.     response.write(t.render(c))
  15.     return response
复制代码
添加我们的路由,打开我们的
  1. testsite/members/urls.py
复制代码
文件:
  1. path('csv-template/', views.some_view_tem, name='csv'),
复制代码
在当前目录下面的
  1. templates
复制代码
文件夹创建我们的模板文件
  1. my_template_name.txt
复制代码
  1. {% for row in data %}"{{ row.0|addslashes }}", "{{ row.1|addslashes }}", "{{ row.2|addslashes }}", "{{ row.3|addslashes }}", "{{ row.4|addslashes }}"
  2. {% endfor %}
复制代码
浏览器访问
  1. http://127.0.0.1:8080/members/csv-template
复制代码
流式输出文件:

就可以得到我们自定义模板的
  1. csv
复制代码
文件。

二、如何创建 PDF 文件

由于
  1. python
复制代码
拥有出色的开源
  1. ReportLab Python PDF
复制代码
库,使得我们动态生成
  1. pdf
复制代码
非常有优势。
首先我们安装ReportLab 库:
  1.   py -m pip install reportlab
复制代码
我们可以看到下列结果:

使用
  1. django
复制代码
动态生成
  1. pdf
复制代码
的关键在于
  1. ReportLab API
复制代码
作用于类似文件的对象,而
  1. Django
复制代码
  1. FileResponse
复制代码
对象接受类似文件的对象。
打开我们的
  1. testsite/members/views.py
复制代码
视图文件:
  1. import io
  2. from django.http import FileResponse
  3. from reportlab.pdfgen import canvas
  4. def some_view_pdf(request):
  5.     buffer = io.BytesIO()
  6.     p = canvas.Canvas(buffer)
  7.     p.drawString(100, 100, "Hello world.")
  8.     p.showPage()
  9.     p.save()
  10.     buffer.seek(0)
  11.     return FileResponse(buffer, as_attachment=True, filename="hello.pdf")
复制代码
代码里面我讲一下大概的含义:

  • 响应将 根据文件扩展名 自动设置
    1. MIME
    复制代码
    类型
    1. application/pdf
    复制代码
    。这就告诉浏览器该文档是
    1. PDF
    复制代码
    文件,而不是
    1. HTML
    复制代码
    文件或通用
    1. application/octet-stream
    复制代码
    二进制内容。
    1. as_attachment=True
    复制代码
    传递给时
    1. FileResponse
    复制代码
    ,它会设置适当的
    1. Content-Disposition
    复制代码
    标头,并告诉网络浏览器弹出一个对话框,提示/确认如何处理文档,即使机器上设置了默认值。如果
    1. as_attachment
    复制代码
    省略该参数,浏览器将使用已配置用于
    1. PDF
    复制代码
    的任何程序/插件来处理
    1. PDF
    复制代码

    1. filename
    复制代码
    定义你需要输出的
    1. pdf
    复制代码
    名字。浏览器将在“另存为…”对话框中使用它。
  • 可以挂接到
    1. ReportLab API
    复制代码
    :作为第一个参数传递的相同缓冲区
    1. canvas.Canvas
    复制代码
    可以提供给该类
    1. FileResponse
    复制代码

  • 所有后面的
    1. PDF
    复制代码
    生成方法均在
    1. PDF
    复制代码
    对象(上面例子中为p)上调用,而不是在 上调用
    1. buffer
    复制代码

    1. showPage()
    复制代码
    最后,调用并
    1. save()
    复制代码
    查看
    1. PDF
    复制代码
    文件非常重要。
添加我们的路由,打开我们的
  1. testsite/members/urls.py
复制代码
文件:
  1. path('csv-stream/', views.some_streaming_csv_view, name='csv'),
复制代码
浏览器访问
  1. http://127.0.0.1:8080/members/pdf
复制代码


打开
  1. pdf
复制代码
文件,就可以看到我们自动输出的
  1. pdf
复制代码
文件:
  1. ReportLab
复制代码
并不是线程安全的。
所以一些小伙伴在构建
  1. PDF
复制代码
生成
  1. Django
复制代码
视图时出现的奇怪问题,这些视图就是由于许多人同时访问造成的。

三、总结

虽然
  1. csv
复制代码
文件和
  1. pdf
复制代码
文件的动态生成技术很常见,也是业务中经常用到的,我们文中所用到的只是其中的某个包,比如
  1. reportlab
复制代码

  1. django
复制代码
官方的
  1. packages
复制代码
有更详细不同包的比较,以及他们的使用方式,
  1. https://djangopackages.org/grids/g/pdf/
复制代码

利用这两个工具结合我们的
  1. django
复制代码
视图,就完全的能和我们自己开发的系统结合起来了。
根据相应的显示字段动态生成一切我们想要的文件,是非常方便的。
以上就是Django使用视图动态输出CSV以及PDF的操作详解的详细内容,更多关于Django视图输出CSV及PDF的资料请关注脚本之家其它相关文章!

来源:https://www.jb51.net/python/323406v3s.htm
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具