Django2.0-views(6)-csv檔案
阿新 • • 發佈:2018-12-20
生成CSV檔案
有時候我們做的網站,需要將一些資料,生成有一個CSV
檔案給瀏覽器,並且是作為附件的形式下載下來。、
生成小的CSV檔案
用Python
內建的csv
模組來處理csv
檔案,並且使用HttpResponse
來將csv
檔案返回回去。
import csv
from django.http import HttpResponse
def csv_view(request):
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="somefilename.csv"'
# 下面類似於
# with open("xxx.csv", "w") as fp:
# csv.writer(fp)
writer = csv.writer(response) #HttpResponse重寫了write方法,這裡可以當成控制代碼使用
writer.writerow(['username', 'age', 'height', 'weight']) #寫一行
writer.writerow(['zhiliao', '18', '180', '110'])
return response
- 在初始化
HttpResponse
的時候,指定了Content-Type
text/csv
,這將告訴瀏覽器,這是一個csv
格式的檔案而不是一個HTML
格式的檔案,如果用預設值,預設值就是html
,那麼瀏覽器將把csv
格式的檔案按照html
格式輸出 - 第二個在
response
中新增一個Content-Disposition
頭,這個東西是用來告訴瀏覽器該如何處理這個檔案,我們給這個頭的值設定為attachment;
,那麼瀏覽器將不會對這個檔案進行顯示,而是作為附件的形式下載,第二個filename="somefilename.csv"
是用來指定這個csv
檔案的名字。 - 使用
csv
模組的writer
方法,將相應的資料寫入到response
中。
將csv
檔案定義成模板
我們還可以將csv
Django
內建的模板系統,並給這個模板傳入一個Context
物件,這樣模板系統就會根據傳入的Context
物件,生成具體的csv
檔案。
模板檔案:
{# abc.txt #}
{# 下面會換行 #}
{% for row in rows %}
{{row.0}} {{row.1}}
{% endfor %}
{# 下面這個不會換行 #}
{% for row in rows %}{{row.0}}{row.1}
{% endfor %}
檢視函式:
from django.http import HttpResponse
from django.template import loader
def some_view(request):
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="somefilename.csv"'
context = {
'rows': [
['name', 'jack'],
['age', 22]
]
}
template = loader.get_template('abc.txt') #載入模版
csv_template = template.render(context) #渲染模版
response.content = csv_template #將渲染好的模版新增金response裡
return response
生成大的CSV檔案
以上的例子是生成的一個小的csv
檔案,如果想要生成大型的csv
檔案,那麼以上方式將有可能會發生超時的情況(伺服器要生成一個大型csv檔案,需要的時間可能會超過瀏覽器預設的超時時間)。這時候我們可以藉助另外一個類,叫做StreamingHttpResponse
物件,這個物件是將響應的資料作為一個流返回給客戶端,而不是作為一個整體返回。示例程式碼如下:
from django.http import StreamingHttpResponse
def large_csv(request):
response = StreamingHttpResponse(content_type='text/csv')
response["Content-Disposition"] = "attachement;filename='large.csv'"
rows = ("Row {}, {}\n".format(row, row) for row in range(0, 100000))
response.streaming_content = rows # 需要可迭代的
return response
注意:StreamingHttpResponse
會啟動一個程序來和客戶端保持長連線,所以會很消耗資源。所以如果不是特殊要求,儘量少用這種方法。
關於StreamingHttpResponse
這個類是專門用來處理流資料的。使得在處理一些大型檔案的時候,不會因為伺服器處理時間過長而到時連線超時。這個類不是繼承自HttpResponse
,並且跟HttpResponse
對比有以下幾點區別:
- 這個類沒有屬性
content
,相反是streaming_content
。 - 這個類的
streaming_content
必須是一個可以迭代的物件。 - 這個類沒有
write
方法,如果給這個類的物件寫入資料將會報錯。
注意:StreamingHttpResponse
會啟動一個程序來和客戶端保持長連線,所以會很消耗資源。所以如果不是特殊要求,儘量少用這種方法。