Quantcast
Channel: pandas - よちよちpython
Viewing all articles
Browse latest Browse all 30

【Flask Pandas】売上データからドロップダウンメニューで担当者を指定して抽出、ページに表示する

$
0
0

今回は、PandasのデータフレームをWebページに表示させます。
売上データから担当者を指定して表示させるアプリ。



実行環境

  • Windows10
  • Anaconda 4.11.0
  • Python3.9.7
  • VSCode 1.63.2
  • 外部ライブラリ
    • Flask 2.0.2
    • colorama 0.4.4 (Windowsはたぶん手動でインストールが必要
    • Pandas 1.3.5



アプリの仕様・操作手順など

df
No売上日担当者商品単価数量
012022-01-09立花宗茂牛乳1399
122022-01-08島津義弘イチゴ4166
232022-01-05島津義弘牛乳2813
342022-01-03上杉謙信牛乳1516
452022-01-06豊臣秀吉牛乳4741
.....................
9959962022-01-01上杉謙信バター15010
9969972022-01-02上杉謙信10710
9979982022-01-10織田信長砂糖4628
9989992022-01-10北条氏康砂糖41610
99910002022-01-05毛利元就22510

1000 rows × 6 columns

上のような売上データがあるとします。(顧客名を入れ忘れた
担当者を指定して、その担当者の売上テーブルを表示するアプリを作ります。

データフレームから条件抽出するにはdf.query()df[df['カラム名']==値]などを使えばできます。

df[df['担当者']=='織田信長']
No売上日担当者商品単価数量
12132022-01-03織田信長3841
42432022-01-09織田信長イチゴ1449
55562022-01-10織田信長砂糖4553
72732022-01-07織田信長小麦粉1384
73742022-01-07織田信長バター3356
.....................
9709712022-01-03織田信長バター4881
9739742022-01-10織田信長バター4372
9819822022-01-04織田信長4785
9839842022-01-01織田信長チョコレート2972
9979982022-01-10織田信長砂糖4628

108 rows × 6 columns

メニューから担当者を選択して、↑のような表をWebページに表示するのが今回の目標です。



データフレームに.to_html()メソッドを付けると(df.to_html())、テーブルがhtmlコードに変換されます。そのオブジェクトをFlaskのテンプレートに渡せばテーブルを表示してくれるはずです。

  • 担当者のユニークなリストを取得するには
df['担当者'].unique().tolist()
['立花宗茂', '島津義弘', '上杉謙信', '豊臣秀吉', '北条氏康', '毛利元就', '武田信玄', '織田信長', '徳川家康']

このリストをホームページに設置するドロップダウンメニューのselectタグに渡して、テンプレートエンジンの記法のfor文で回せばメニューが出来る。



アプリの操作手順

  1. ホームページに設置したドロップダウンメニューで担当者を選択し、送信する。
  2. 送信された担当者の売上データをデータフレームから抽出。
  3. テーブルで表示



20220117015645

ホームページ。ドロップダウンメニューで担当者を選択し、送信。



20220117015810

指定した担当者の売上データが表示される。



20220117015858

CSSでスタイル変更してみた。



ディレクトリ構成とファイルの中身

アプリはショボいんですが…

$ tree flask_sample

flask_sample/
├── app.py (Flaskを動かす)
├── static
│   └── css
│       └── style.css (表の装飾。試しに付けた)
├── templates
│   ├── base.html (htmlページのメタ情報テンプレート)
│   ├── index.html (ホームページ。入力欄とボタンを設置)
│   └── result.html (表の出力ページ)
└── uriage_data.py (データフレームの生成用)

3 directories, 6 files



app.py (Flaskを動かす用)

from flask import Flask, render_template, request
from uriage_data import uriage

app = Flask(__name__)

# 売上データ
df, tantou_list = uriage()

# ホームページ@app.route('/')
defindex():
    return render_template('index.html', tantou_list=tantou_list)

# 入力値の表示ページ@app.route('/result', methods=['GET', 'POST'])
defresult():
    # 担当者名を取得
    tantou_name = request.form.get('tantousya')
    # データフレームから指定担当者の売上を抽出
    df_tantou = df[df['担当者']==tantou_name]
    # 指定担当者のデータフレームをhtmlに変換
    df_tantou = df_tantou.to_html()

    if request.method == 'POST':
        return render_template('result.html', tantou_name = tantou_name, dataframe = df_tantou)
    else:
        return render_template('index.html')

if __name__=='__main__':
    app.run(debug=True)

uriage_data.py (データフレーム生成用)

app.pyの中に書いてもよかったのですが、読みにくいかなと思って分けました。

import pandas as pd
import random
random.seed(0)

# 売上データを生成defuriage():
    df = pd.DataFrame({
        'No' : range(1, 1001),
        '売上日' : random.choices(pd.date_range(start='2022/1/1', freq='d', periods=10), k=1000),
        '担当者' : random.choices('織田信長 豊臣秀吉 徳川家康 毛利元就 北条氏康 武田信玄 上杉謙信 島津義弘 立花宗茂'.split(), k=1000),
        '商品' : random.choices('卵 牛乳 砂糖 小麦粉 バター チョコレート チーズ イチゴ'.split(), k=1000),
        '単価' : random.choices(range(100, 501), k=1000),
        '数量' : random.choices(range(1,11), k=1000)
    })

    # 担当者をリストで取得
    tantou_list = df['担当者'].unique().tolist()

    return df, tantou_list

base.html (htmlファイルのメタ情報)

htmlファイルのだいたい共通している部分なので別に分ける。

<!DOCTYPE html><htmllang="ja"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=device-width, initial-scale=1.0"><linkrel="stylesheet"href="static/css/style.css"><!-- タイトル --><title>Flaskサンプル-{% block title %}{% endblock %}</title></head><!-- コンテンツ内容 --><body>
    {% block content %}
    {% endblock %}
</body></html>

外部CSSファイルを用意したので、<link rel="stylesheet" href="static/css/style.css">を付けました。「style.css」というファイルを「static/css/」に保存しているので。
これを書くだけで自動的にCSSファイルを読み込んでくれます。

index.html (ホームページ)

入力欄とボタンを設置

{% extends 'base.html' %}

{% block title %}ホームページ{% endblock %}

{% block content %}
<formaction="/result"method="POST"><p>担当者:
    <selectname="tantousya">
    {% for i in tantou_list %}
    <optionvalue="{{ i }}">{{ i }}</option>
    {% endfor %}
    </select></p><p><inputtype="submit"value="送信"></p></form>
{% endblock %}

selectタグoptionタグでドロップダウンメニューを実装できます。 app.pyファイルから渡されたtantou_listをfor文で回してメニューを作っています。
tantou_listuriage_data.pyで売上データフレームから取り出した担当者リスト。
送信ボタンを押すと、selectタグname属性'tantousya'はFlask側app.pyに送信されます。

result.html (指定担当者の表出力ページ)

{% extends 'base.html' %}

<!-- タイトル表示 -->
{% block title %}{{ tantou_name }}さんの売上データ{% endblock %}

<!-- コンテンツ内容の表示 -->
{% block content %}

{{ dataframe | safe }}

{% endblock %}

htmlテンプレートファイルにhtmlコードを渡すと、自動でエスケープされてページにコードが文字列で表示されてしまいます。
{{ dataframe | safe }}と書いていますが、パイプ|で繋いでsafeとすることでエスケープが外れてhtmlコードが実行表示できるようになります。

style.css (指定担当者売上テーブルの装飾用)

html/css未学習のため、cssの書き方が分からず、適当にネットからコピペ・改造したものです。外部CSSの効かせ方を把握する目的。

.dataframe{/*テーブルの縦幅が100px以上の場合スクロール*/height: 100px;
    /*縦スクロール*/overflow: scroll;
}/* 一覧表の調整 */td{border-bottom: 1pxsolidblack;
    border-left: 1pxsolidblack;
    border-right: 1pxsolidblack;
    text-align: center;       
}th{background-color: #ddffeb;
    border-bottom: solidblack;
    border-left: solidblack;
    border-right: solidblack;
    border-top: solidblack;
    border-width: 2px;
    position: sticky;
    top: 0;
    text-align: center; 
}/* カラムの調整 */.column{overflow: hidden;/*スクロール時にカラム名を固定*/text-overflow: ellipsis;
}

テーブルが縦長になったのでスクロールバーをつけようとしたが、よく分からない。とりあえずCSSは効いてるようだ。



実行

ターミナルでFlaskを実行し、サーバが起動したらブラウザでローカルホストの5000番にアクセス。

PS > python app.py

ブラウザで127.0.0.1:5000localhost:5000にアクセス。
ホームページが表示される。あとは上の「アプリの操作手順」通り。



おわりに

通常、データはデータベースに登録し、表示する際にSQLなどで取り出すと思います。今回のようにデータフレームをテーブルにして表示することはしないとは思いますが、どうなるかの確認でした。
ショボいアプリなのにファイルが6個もある。変数値がファイルをまたいでアッチコッチに飛ぶので、設計書か何かで動作の全体像を把握しないと混乱する。Webやってる人スゲェ。



以上です。


Viewing all articles
Browse latest Browse all 30

Trending Articles