生成CSV文件
有时候我们做的网站,需要将一些数据,生成有一个CSV文件给浏览器,并且是作为附件的形式下载下来
生成小的CSV文件
处理方法:使用Python内置的CSV模块来处理CSV文件,且使用HttpResponse来将CSV文件返回回去
例1:
⑴编辑视图
⑵下载效果
注:
1、在初始化HttpResponse的时候,指定了Content-Type为text/csv,这将告诉浏览器,这是一个csv格式的文件而不是一个HTML格式的文件
⑴如果用默认值,默认值就是html,那么浏览器将把csv格式的文件按照html格式输出,这肯定不是我们想要的
2、还在response中添加一个Content-Disposition头(属性),这个东西是用来告诉浏览器该如何处理这个文件
⑴给这个头的值设置为attachment,那么浏览器将不会对这个文件进行显示,而是作为附件的形式下载:attachment
⑵filename=bookInfo.csv是用来指定这个csv文件的名字:文件名字及其后缀名
3、使用csv模块的writer方法,将相应的数据写入到response中:将一行数据定义成一个列表,将列表整体写到一行中
4、接入生成CSV API非常简单:仅需将response作为第一个参数传给csv.writer
⑴csv.writer函数期望一个类文件对象,而HttpResponse对象满足该要求
5、要按行输出CSV文件,调 writer.writerrow,传入一个iterable 参数
6、CSV模块为你处理了引号,所以你无需担心包含引号或逗号的字符串的转义问题。只需为writerow() 传入原始字符串,它为你处理好一切
例1_1:从数据库中查询数据并写入到CSV文件中
⑴查看数据库数据
⑵编辑视图
⑶下载效果
将CSV文件定义成模板
1、还可以将csv格式的文件定义成模板,然后使用Django内置的模板系统,并给这个模板传入一个Context对象,这样模板系统就会根据传入的Context对象,生成具体的csv文件
2、即,如果CSV文件内容的格式是一样的话,我们就可以预先定义一个模板,那么之后就可以直接将不同的数据填充到模板中就可以了
例2:
⑴编辑模板:txt文件
⑵编辑视图
⑶下载效果
注:
1、使用模板写入时,只能一次性将所有内容全部写入,不能分批次写入:不然后面的绘覆盖前面的
⑴这就是为什么我要先把查询结果"articleResultList.append(articleResult)"加入到列表中的原因
⑵所以个人感觉使用模板写入时也不是很好,也有些局限性
2、因为将"data"键值对传到模板中后需要经过一次遍历,因此articleResultList是一个两层的列表
例2_2:
⑴编辑模板:txt文件
⑵编辑视图
⑶下载效果
注:
1、这个例子中就是直接将查询返回的QuerySet对象传递给模板,然后获取每列的值都是在模板中进行的
⑴QuerySet对象经for标签遍历后得到每个模型类,然后通过"模型类名.列名"获得具体列的值:列名指的是数据库模型类中定义的列名而不是数据库中的列名
2、感觉这里定义的模板txt文件跟前端模板HTML差不多只是后缀名不一样
生成大的CSV文件
1、以上的例子是生成的一个小的csv文件,如果想要生成大型的csv文件,那么以上方式将有可能会发生超时的情况
⑴服务器要生成一个大型csv文件,需要的时间可能会超过浏览器默认的超时时间
⑵这时候我们可以借助另外一个类,叫做StreamingHttpResponse对象,这个对象是将响应的数据作为一个流返回给客户端,而不是作为一个整体返回
2、关于StreamingHttpResponse:
⑴这个类是专门用来处理流数据的。使得在处理一些大型文件的时候,不会因为服务器处理时间过长而到时连接超时。这个类不是继承自HttpResponse,并且跟HttpResponse对比有以下几点区别
⑵这个类没有属性content,相反是streaming_content
⑶这个类的streaming_content必须是一个可以迭代的对象
⑷这个类没有write方法,如果给这个类的对象写入数据将会报错
例3:
⑴编辑视图
⑵下载效果
1、这里我们构建了一个非常大的数据集rows,并且将其变成一个迭代器。然后因为StreamingHttpResponse的第一个参数只能是一个生成器,因此我们使用列表、或元组将其包裹起来
2、注意: StreamingHttpResponse会启动一个进程来和客户端保持长连接,所以会很消耗资源。所以如果不是特殊要求,尽量少用这种方法