ChatGPTと会話しながらWEB上でCSVファイルをインポートできるように実装してみたのでメモメモ

どうもこんにちは。

Pythonチャレンジ第３弾です。

第１弾、第２弾を見ていない方はこちらからご覧ください。

https://qiita.com/PDC-Kurashinak/private/355fcd920aa6803e59f3

https://qiita.com/PDC-Kurashinak/private/41297d8bff6c938dd80e

今回は、WEB上からCSVファイルをインポートして、そのデータをWEB上に可視化するシステムを作ります。

# 実装方法

## 1. Flaskの拡張機能をインストール

ファイルのアップロードを簡単に扱うために、`Flask-WTF`という機能を使用します。
`requirements.txt`に以下を追加します。

```makefile
Flask-WTF==0.15.1
```

## 2. ファイルアップロードフォームの作成

`app.py`に以下のコードを追加します。

```python
from flask_wtf import FlaskForm
from wtforms import FileField, SubmitField
from wtforms.validators import DataRequired

class UploadForm(FlaskForm):
    file = FileField('CSVファイルを選択', validators=[DataRequired()])
    submit = SubmitField('アップロード')
```

## 3. ルーティングを変更

`app.py`のルーティング記述を以下のように変更します。

```python
@app.route('/', methods=['GET', 'POST'])
```

## 4. データ処理の関数(index関数)を変更

`app.py`の関数記述を以下のように変更します。

```python
def index():
    form = UploadForm()
    if form.validate_on_submit():
        file = form.file.data

        # サンプルデータの読み込み
        df = pd.read_csv(file)

        # データの可視化
        plt.hist(df['some_column'])

        # プロットを画像として保存
        img = io.BytesIO()
        plt.savefig(img, format='png')
        img.seek(0)

        # 画像をBase64でエンコード
        plot_url = base64.b64encode(img.getvalue()).decode()

        return render_template('result.html', plot_url=plot_url)
    return render_template('upload.html', form=form)
```

## 5. HTMLファイルの作成

`templates`ディレクトリに`upload.html`と`result.html`というHTMLファイルを作成します。

[upload.html]
```html
<!DOCTYPE html>
<html>
<head>
  <title>CSVアップロード</title>
</head>
<body>
  <form method="POST" enctype="multipart/form-data">
    {{ form.hidden_tag() }}
    <p>
      {{ form.file.label }}<br>
      {{ form.file() }}
    </p>
    <p>{{ form.submit() }}</p>
  </form>
</body>
</html>
```

[result.html]
```html
<!DOCTYPE html>
<html>
<head>
  <title>結果の表示</title>
</head>
<body>
  <h1>result</h1>
  <img src="data:image/png;base64,{{ plot_url }}" alt="Plot Image">
  <br>
  <a href="/">戻る</a>
</body>
</html>
```

## 6. 秘密鍵と保存先URLの設定

`app.py`に以下のコードを記述します。

```python
from config import SECRET_KEY
from config import UPLOAD_PATH

app = Flask(__name__)
app.config['SECRET_KEY'] = SECRET_KEY
app.config['UPLOAD_FOLDER'] = UPLOAD_PATH
```

`config.py`ファイルを作成し、以下を記述します。

```python
SECRET_KEY = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"   # ランダムな文字列を指定してください
UPLOAD_PATH = "/yyyy/yyyy/yyyyyyyyy"    # ファイルをアップロードするパスを指定してください
```

## 7. 実行

ターミナルで`docker-compose up --build`を実行します。

実行したら、`http://localhost:5001/`にアクセスします。

# 結果

ページにアクセスして以下のページが表示されるはずです。

![スクリーンショット 2023-09-16 18.09.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711491/44b872e2-5f5c-0546-772d-74c73c427cc4.png)

次に、CSVファイルをアップロードしてアップロードをクリックします。

![スクリーンショット 2023-09-16 18.10.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711491/7c44f03e-989f-0fea-2720-0f8b5f36127a.png)

グラフが表示されていれば成功です。

（CSVファイルの内容は以下のようにしてください。）

```
id,some_column
1,100
2,200
3,300
4,400
5,150
6,200
7,250
8,300
9,350
```

# まとめ

今回はCSVファイルをアップロードして結果をグラフ表示できるまで実装してみました。

かなり実際のアプリケーションに近づいたかなと思います。

次の追加機能が思い浮かんだらまた実装してみようと思います。

以上

# ソースコードはこちら

https://github.com/pdc-kurashina/python_sample_qiita_01