Flask 結合 pandas.DataFrame 輸出文件(excel/csv)

Flask 是使用 Python 編寫的一個輕量級web框架,使用 Flask 可以快速的搭建起一個網站,輕量級體現在框架提供了基礎的應用框架(定義app、templates、Field等),其餘目的的可以使用外部包達成。
pandas 是基於 Numpy 的一種工具,該工具是爲了解決數據分析而創建的,在 Numpy 的快速計算基礎上增加了行和列名,可以讀取文件、數據庫數據並進行交互,pandas.DataFrame 是 pandas 中的一種表型數據結構。
本文就是使用功能 pandas.DataFrame 將數據流以表格的形式返回到客戶端。

一、建立應用

使用 flask 創建應用,並創建相應文件

│	├── flask                            // 源碼目錄
│   ├── templates                          // 模板
│   │   ├── index.html                        // 首頁頁面
│   │   ├── extraction.html                   // 提取頁面
│   ├── app.py                             // 應用
│   ├── textraction.py                     // 提取應用

1.app.py 代碼

from flask import Flask, render_template
import os
from extraction import Submit, GetData


app = Flask(__name__)
SECRET_KEY = os.urandom(32)
app.config['SECRET_KEY'] = SECRET_KEY


@app.route('/')
def index():
	# 首頁
    return render_template('index.html')


@app.route('/extraction/', methods=['GET', 'POST'])
def extraction():
	# 提取頁面
    form = Submit()
    if form.validate_on_submit():
        return GetData()()
    return render_template('extraction.html', form=form)


if __name__ == "__main__":
    app.run(host="127.0.0.1", port=80)

首先是註冊app,然後定義首頁url和提取頁面url以及對應邏輯。其中extraction頁面中要是用 GET 和 POST 兩種方法,因爲 GET 方法返回頁面,POST 方法返回數據

2.index.html 代碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首頁</title>
</head>
<body>
這是首頁
<hr />
{% block body %}
<a class="extraction" href="/extraction/"> 數據提取演示 </a>
{% endblock %}
</body>
</html>

定義頁面內容,這裏沒有太多東西,就是簡單說明這是首頁,並且提供一個鏈接指向提取頁面,而且是用 {% block body %} 將這部分變成一個塊,可以在以後繼續使用這個模板。

3. extraction.html 代碼

{% extends "index.html" %}
{% block body %}
<form action="" method="post" novalidate>
    {{ form.hidden_tag() }}
    <p>{{ form.submit() }}</p>
</form>
{% endblock %}

使用 {% extends “index.html” %} 直接繼承模板,直接重寫body塊的內容,形成一個表單。

二、使用 pandas.DataFrame 製造數據

import pandas as pd
data = pd.DataFrame(['Geeks', 'For', 'Geeks', 'is', 'portal', 'for', 'Geeks'])

三、使用 make_response 將數據流返回客戶端

Flask 官方提供了 make_response 將數據封裝成 response 類以供開發者使用。具體介紹可以搜索點擊鏈接apimake_response查看。
方法很簡單,直接將數據封裝成 response 然後返回

response = make_response(value)
return response

四、將 pandas.DataFrame 的數據流寫入response並返回

返回頁面的數據不能直接使用 pandas.DataFrame, 因爲這只是一個數據結構,所以需要將 pandas.DataFrame 轉化爲數據流,然後以需要的形式發送至客戶端。
這裏的數據流實現方式就是使用 IO 模塊將數據寫入內存,最後再“讀取”到 make_response 中。

out = io.BytesIO()
writer = pd.ExcelWriter(out, engine='xlsxwriter')
data.to_excel(excel_writer=writer, index=False, sheet_name='示例')
writer.save()
writer.close()

這樣數據流就在 out 對象中了,然後就可以結合 make_response 製造 response 對象。
下面直接貼成型代碼:

from flask_wtf import FlaskForm
import pandas as pd
import io
from flask import make_response
from wtforms import SubmitField
import time


class GetData:
    def __init__(self):
        self.data = pd.DataFrame(['Geeks', 'For', 'Geeks', 'is', 'portal', 'for', 'Geeks'])

    def __call__(self):
        df = self.data
        out = io.BytesIO()
        writer = pd.ExcelWriter(out, engine='xlsxwriter')
        df.to_excel(excel_writer=writer, index=False, sheet_name='示例')
        writer.save()
        writer.close()
        file_name = time.strftime('%Y%m%d', time.localtime(time.time())) + '.xlsx'
        response = make_response(out.getvalue())
        response.headers["Content-Disposition"] = "attachment; filename=%s" % file_name
        response.headers["Content-type"] = "application/x-xls"
        """ 如果輸出的是 csv 文件
        df = self.data
        out = io.StringIO()
        df.to_csv(out, index=False)
        file_name = time.strftime('%Y%m%d', time.localtime(time.time())) + '.csv'
        response = make_response(out.getvalue())
        response.headers["Content-Disposition"] = "attachment; filename=%s" %file_name
        response.headers["Content-type"] = "text/csv"
        """
        return response


class Submit(FlaskForm):
    submit = SubmitField('提取數據')

註釋部分還提供了 csv 文件的處理方法,不同的地方在數據寫入方式 df.to_csv 和 response.headers 的 Content-type 部分(可以參照HTTP Content-type 對照表

五、擴展

一般輸出的會是有多個數據表,但是數據流只有一份,所以如果想要同時輸出多份數據只能將數據寫入一個文件或將多個文件打包成壓縮文件,總之最後返回的只能是一個數據。比如上面的例子可以

df.to_excel(excel_writer=writer, index=False, sheet_name='示例')
df.to_excel(excel_writer=writer, index=False, sheet_name='示例1')

這樣在 excel 文件中就會包含兩個sheet “示例” 和“示例1”。

所有文件可以下載

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