django開發系列:視圖高級之CSV文件

django開發系列:視圖高級之CSV文件

生成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
  1. 在初始化HttpResponse的時候,指定了Content-Type爲text/csv,這將告訴瀏覽器,這是一個csv格式的文件而不是一個HTML格式的文件,如果用默認值,默認值就是html,那麼瀏覽器將把csv格式的文件按照html格式輸出
  2. 第二個在response中添加一個Content-Disposition頭,這個東西是用來告訴瀏覽器該如何處理這個文件,我們給這個頭的值設置爲attachment;,那麼瀏覽器將不會對這個文件進行顯示,而是作爲附件的形式下載,第二個filename="somefilename.csv"是用來指定這個csv文件的名字。
  3. 使用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會啓動一個進程來和客戶端保持長連接,所以會很消耗資源。所以如果不是特殊要求,儘量少用這種方法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章