閱讀本文大概需要6分鐘
在上一篇文章,我介紹了CSV是什么?CSV有哪些優(yōu)點(diǎn)?如何使用等等?并且最后我們用一個(gè)例子簡(jiǎn)單講解了如何使用Python模塊CSV進(jìn)行導(dǎo)出后綴為.csv的文本文件。
具體文章參看:Python模塊之CSV導(dǎo)出(一)
其實(shí)例子用于異步導(dǎo)出數(shù)據(jù)文件是夠了,但工作中我們可能還需要結(jié)合我們Web框架進(jìn)行更復(fù)雜的CSV導(dǎo)出。
所以今天我們的目的就是結(jié)合Python Django框架進(jìn)行分享CSV導(dǎo)出的另外一種方式。
這里面我們需要安裝一個(gè)第三方包djangorestframework-csv
:
方法如下,使用pip安裝到你virtualenv構(gòu)建的虛擬環(huán)境中,當(dāng)然你如果使用了docker進(jìn)行環(huán)境隔離這兒也可以直接安裝你docker容器中。
$ pip install djangorestframework-csv
有些同學(xué)可能不太明白,明明是Django框架怎么和Django REST Framework(簡(jiǎn)稱DRF)扯上關(guān)系了,簡(jiǎn)單解釋一下,由于我們Django API開發(fā)常常配合DRF進(jìn)行,所以一般都是一起安裝使用了的,把Django和DRF結(jié)合起來整個(gè)RESTFul API開發(fā)效率能大大提高,建議稍微大一點(diǎn)工程化項(xiàng)目都去使用DRF。
使用方式如下:
繼承CSVRenderer 定義一個(gè)自己的Render類
將要生成CSV的字典數(shù)據(jù)傳入該類的方法render方法
使用HttpResponse或者StreamingHttpResponse進(jìn)行返回
看起來是不是簡(jiǎn)單方便,確實(shí)就是這么簡(jiǎn)單,下面我們看一個(gè)例子。
廢話不多說,直接上代碼,先定義一個(gè)自己的CSV Render
# 定義CSV Renderfrom rest_framework_csv import renderersclass YourModelRender(renderers.CSVStreamingRenderer): header = [ 'phone', 'remark', 'create_time', ] labels = dict([ ('phone', u'聯(lián)系電話'), ('remark', u'備注'), ('create_time', u'時(shí)間'), ])
這里使用label dict屬性將自定義標(biāo)簽應(yīng)用于CSVRenderer,其中每個(gè)鍵對(duì)應(yīng)于表頭header,值對(duì)應(yīng)于該表頭header的自定義標(biāo)簽,這樣我們各個(gè)值就能和header對(duì)應(yīng)起來。
Django導(dǎo)出的view方法,源碼如下。
@list_route(methods=['get']) # 這是DRF生成URL的方式,沒用過的可以忽略。 def example_export_csv(self): ''' CSV 案例 ''' queryset = YourModel.objects.all() renderer = YourModelRender() data = ( YourModelListSerializer(instance).data ## 得到字典數(shù)據(jù) for instance in queryset ) response = StreamingHttpResponse( renderer.render(data), content_type='text/csv' ) response['Content-Disposition'] = 'attachment; filename='somefilename.csv'' return response
上面幾行代碼是不是看起來很簡(jiǎn)單,確實(shí)就是這么簡(jiǎn)單,簡(jiǎn)單的背后是rest_framework_csv幫我們做了導(dǎo)出功能,底層實(shí)現(xiàn)還是昨天我說的那種方式write,writerow的方式。
這里面簡(jiǎn)單解釋一下:
YourModelListSerializer寫過DRF的同學(xué)知道這個(gè)就是定義數(shù)據(jù)處理邏輯校驗(yàn),格式化什么等操作。這里面我們通過YourModelListSerializer復(fù)用了其他模塊處理邏輯,如RRESTFul的列表數(shù)據(jù)展示。
這樣大大減少了我們導(dǎo)出CSV還需要去重新處理多個(gè)字段組裝,過濾,變換等邏輯。因?yàn)橥覀兞斜硇枰故緮?shù)據(jù)就是我們CSV要導(dǎo)出的數(shù)據(jù)。記得幾年前那會(huì)兒導(dǎo)出數(shù)據(jù)還要自己重新組裝數(shù)據(jù),真是酸爽。
我們這兒用了StreamingHttpResponse,將文件內(nèi)容進(jìn)行流式傳輸,對(duì)于實(shí)時(shí)導(dǎo)出大文件,可以避免服務(wù)器斷開連接。比起HttpResponse更節(jié)約內(nèi)存。
上面我們使用DRF,并且也用了看起來復(fù)雜的YourModelListSerializer這種復(fù)雜的概念,主要目的是讓大家知道DRF的方式,至于普通使用Django其實(shí)我們完全可以把renderer.render(data)
換為上一篇文章(writer.writerow(row) for row in rows)
這種形勢(shì)。
關(guān)于CSV我們還可以用Django模板形式進(jìn)行,和我們用rest_framework_csv模塊思路差不多
簡(jiǎn)單給一個(gè)官方案例:
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 = Context({ 'data': csv_data, })response.write(t.render(c))return response
雖然思路相似,但過程實(shí)現(xiàn)會(huì)麻煩較多,你要去切換模板代碼書寫,渲染,不推薦這種方式。
最后關(guān)于CSV我們就介紹到這里,結(jié)合上一篇主要兩種方式:
普通CSV導(dǎo)出+Celery Beat定時(shí)導(dǎo)出
Django + DRF + 實(shí)時(shí)導(dǎo)出
原理都是Python內(nèi)置模塊CSV的一些變換,只是結(jié)合第三庫(kù),讓我們操作更快更方便起來。
聯(lián)系客服