电竞比分网-中国电竞赛事及体育赛事平台

分享

更高效的Python CSV文件導(dǎo)出

 鷹兔牛熊眼 2019-01-17

閱讀本文大概需要6分鐘

在上一篇文章,我介紹了CSV是什么?CSV有哪些優(yōu)點(diǎn)?如何使用等等?并且最后我們用一個例子簡單講解了如何使用Python模塊CSV進(jìn)行導(dǎo)出后綴為.csv的文本文件。

具體文章參看:Python模塊之CSV導(dǎo)出(一)

其實例子用于異步導(dǎo)出數(shù)據(jù)文件是夠了,但工作中我們可能還需要結(jié)合我們Web框架進(jìn)行更復(fù)雜的CSV導(dǎo)出。

所以今天我們的目的就是結(jié)合Python Django框架進(jìn)行分享CSV導(dǎo)出的另外一種方式。

安裝依賴

這里面我們需要安裝一個第三方包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(簡稱DRF)扯上關(guān)系了,簡單解釋一下,由于我們Django API開發(fā)常常配合DRF進(jìn)行,所以一般都是一起安裝使用了的,把Django和DRF結(jié)合起來整個RESTFul API開發(fā)效率能大大提高,建議稍微大一點(diǎn)工程化項目都去使用DRF。

使用

使用方式如下:

  1. 繼承CSVRenderer 定義一個自己的Render類

  2. 將要生成CSV的字典數(shù)據(jù)傳入該類的方法render方法

  3. 使用HttpResponse或者StreamingHttpResponse進(jìn)行返回

看起來是不是簡單方便,確實就是這么簡單,下面我們看一個例子。

例子

廢話不多說,直接上代碼,先定義一個自己的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'時間'),    ])

這里使用label dict屬性將自定義標(biāo)簽應(yīng)用于CSVRenderer,其中每個鍵對應(yīng)于表頭header,值對應(yīng)于該表頭header的自定義標(biāo)簽,這樣我們各個值就能和header對應(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

上面幾行代碼是不是看起來很簡單,確實就是這么簡單,簡單的背后是rest_framework_csv幫我們做了導(dǎo)出功能,底層實現(xiàn)還是昨天我說的那種方式write,writerow的方式。

這里面簡單解釋一下:

  1. YourModelListSerializer寫過DRF的同學(xué)知道這個就是定義數(shù)據(jù)處理邏輯校驗,格式化什么等操作。這里面我們通過YourModelListSerializer復(fù)用了其他模塊處理邏輯,如RRESTFul的列表數(shù)據(jù)展示。

  2. 這樣大大減少了我們導(dǎo)出CSV還需要去重新處理多個字段組裝,過濾,變換等邏輯。因為往往我們列表需要展示數(shù)據(jù)就是我們CSV要導(dǎo)出的數(shù)據(jù)。記得幾年前那會兒導(dǎo)出數(shù)據(jù)還要自己重新組裝數(shù)據(jù),真是酸爽。

  3. 我們這兒用了StreamingHttpResponse,將文件內(nèi)容進(jìn)行流式傳輸,對于實時導(dǎo)出大文件,可以避免服務(wù)器斷開連接。比起HttpResponse更節(jié)約內(nèi)存。

 其他

上面我們使用DRF,并且也用了看起來復(fù)雜的YourModelListSerializer這種復(fù)雜的概念,主要目的是讓大家知道DRF的方式,至于普通使用Django其實我們完全可以把renderer.render(data)換為上一篇文章
(writer.writerow(row) for row in rows) 這種形勢。

關(guān)于CSV我們還可以用Django模板形式進(jìn)行,和我們用rest_framework_csv模塊思路差不多
簡單給一個官方案例:

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

雖然思路相似,但過程實現(xiàn)會麻煩較多,你要去切換模板代碼書寫,渲染,不推薦這種方式。


最后關(guān)于CSV我們就介紹到這里,結(jié)合上一篇主要兩種方式:

  1. 普通CSV導(dǎo)出+Celery Beat定時導(dǎo)出

  2. Django + DRF + 實時導(dǎo)出

原理都是Python內(nèi)置模塊CSV的一些變換,只是結(jié)合第三庫,讓我們操作更快更方便起來。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多