【web】【django】datatable的button擴展實現純前端下載和copy指定列內容,以及django的HTTPResponse實現下載功能

 

Table of Contents

功能需求描述

一 使用Datatables實現純前端下載、拷貝

二 query db 實現下載(django)


 

 

功能需求描述

用戶需要以網頁爲媒介,從DB里拉取一些數據。

分爲兩種情況:

  • data已經顯示在頁面上 (除了下載還需要拷貝其中某一列)
  • data沒有顯示在頁面上,需要在trigger download的功能時,根據用戶給定的條件,去後臺query data,然後下載下來。

 

一 使用Datatables實現純前端下載、拷貝

對於第一種情況,由於data是通過datatables插件展示的,且已經從DB拉到了頁面上,也就沒有必要爲了下載它們再跑到查詢一遍數據庫了。

datatables已經給了我們封裝好的插件:

(link:https://datatables.net/extensions/buttons/examples/html5/simple.html  )

除了“XXHtml5”以外,還有  copyexcelcsvand pdf 四種。它們與XXHtml5之間的區別暫時還沒有搞清楚。

我使用的是“csv”button,只是這樣寫就可以實現下載的功能:

 table = $('#psumsTable').DataTable( {//不能使用.dataTable。二者返回值不同。在這裏我們需要使用datatable插件自帶的api,因此必須使用DataTable。

//...
"dom": '<"user_button"B>ptlTgi',//指定button到datatable的左上角。會自動生成一個user_button的div,將所有的button包裹起來
 "buttons": [ 
        {extend: 'csv', //button的功能,包括csv,copy,excel等。這裏不能自由發揮,只能使用datatables插件定好的值
        text:'export' //button上顯示的文字
        }
    ],

很簡單,但接下來在實現copy指定的某一行時遇到了困難。因爲默認情況下,該功能會將datatable中所有的行和列都導出/拷貝出來。但我只要其中一列呀,其他的必須去掉。

於是去研究copy的文檔:

也就是說,datatable的button插件提供customize選項。該選項提供三個參數: 被拷貝的data(字符串類型),button 配置對象,以及Datatables的API實例,這個實例是當前button所屬的那個datatable插件的,也就是說,就是我要從中拷貝數據的那個datatable實例。

而它返回的是什麼呢? The value that the function returns is the value that will be used for the export.也就是會被拷貝的數據。

也就是說,我可以使用這個option給我的Datatables API實例(第三個參數),找到我想要下載的那一列,作爲返回值返回即可。

最終的code大致如下:

"buttons": [  
        {extend: 'copy', text: 'Copy',
         customize: function(data, config, api){
            var copy_list = api.column('need_copy:name').data();//注意name的用法。這裏通過這種方式來讓api找到我想copy的那一列
            var copy_data = copy_list .join('\n');  //換行
            alert('Copied to ClipBoard!'); //一個提示,有沒有都行。
            return copy_data;
            }
        },

        {extend: 'csv', text:'export'} //下載功能。前面提到了。
    ],
//...
 "columns": [
    //...
     { "data": "column_n", "name": 'need_copy' },

注意上例中的api.column('need_copy:name').data()。因爲實現這個功能還有一個坎兒:如何找到我要的那一列。

這就要查Datatables的column-selector了: https://datatables.net/reference/type/column-selector

同樣的,csv等button也有customize選項。也可以實現類似的定製化功能。

 

二 query db 實現下載(django)

以前是這樣實現的:

step1:根據前臺傳回來的搜索條件,到db裏頭query data。

step2:使用FileResponse下載下來。

代碼也很簡單,網上一搜一大把:

from django.http import FileResponse
import pandas as pd

conn = pymssql.connect(...)  # 連DB
df = pd.read_sql(sql, conn)  # query出來的data存在df中。df是dataframe

df.to_csv(csv_file, encoding='utf_8_sig')  # csv_file是文件路徑。

# add data to response
file = open(csv_file, 'rb')
response = FileResponse(file)
response['Content-Type'] = 'application/octet-stream'
response['Content-Disposition'] = 'attachment;filename="%s"' % output_file_name

前臺js的話只需要location.href = XXX, 讓上面這段代碼可以執行就行了。

氮素!

這裏頭有一個隱形天坑!

注意到這句code了沒有:

df.to_csv(csv_file, encoding='utf_8_sig')

它是將從db中拉出來的data先以csv格式保存在某個地方,然後再在後面打開使用FileResponse,將其傳遞給瀏覽器,讓用戶下載。

不是,我都要下載了,還找個地方存文件幹嘛??脫褲子放屁???

但這一次萬能的度娘沒能直接告訴我答案。網絡上能查找到的例子,多是將已經存在的文件下載下來。

我就不能直接把dataframe裏頭的data直接下載下來嗎????(仰天長嘯!)

於是淺淺地翻閱了一下django的官方文檔:

https://docs.djangoproject.com/en/dev/ref/request-response/

HttpResponse 條目下:

嗯?因缺思廳。

那麼這個“my_data”從哪裏搞呢?

再去百度dataframe的to_csv()的文檔:https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.to_csv.html

也就是說,如果我不對to_csv指定輸出文件名,它就會將csv data以字符串的形式返回出來。

這不就是我要的my_data麼!

然後就很順利了:

    output_file_name = ''  # 這個文件名給用戶看的,會在瀏覽器中顯示
    response = HttpResponse(df.to_csv(encoding='utf_8_sig'))
    response['Content-Type'] = 'application/octet-stream'
    # response['Content-Type'] = 'text/csv'
    response['Content-Disposition'] = 'attachment;filename="%s"' % output_file_name

齊活~

另外,有關content_type和content_description的資料:

http://tools.jb51.net/table/http_content_type/

https://www.jianshu.com/p/4c52cb691f54

 

 

 

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