【Flask】中規模な開発のディレクトリ構成を考える

Flaskの開発にあたり、

- 個人開発の範疇
- app.pyに全部書くのは冗長

という中規模な場合のディレクトリ構成を、自分なりに作成しました。

```
.
├── flask_app/
│   ├── __init__.py             <- 初期設定
│   ├── app.py                  <- appを読み込む
│   ├── models.py               <- DBテーブルを定義
│   ├── static/                 <- 静的ファイルを格納
│   │   ├── css/
│   │   └── js/
│   ├── templates/              <- htmlファイルを格納
│   │   ├── common/
│   │   │   └── layout.html
│   │   ├── index.html
│   │   ├── sample.html
│   │   └── ...
│   └── controllers/            <- コントローラ
│       ├── index.py
│       ├── sample.py
│       └── ...
├── instance/                   <- 機密情報を格納
│   ├── config.py               <- appの設定を書く
│   └── sampleDB.db
├── manage.py                   <- データベース作成用
├── .env                        <- 環境変数を定義
├── .gitignore
├── README.md
└── requirements.txt
```
<br>

下記、ソースコードです。

https://github.com/Koichi73/Flask-Template

<br>

## \_\_init__.py
- アプリの初期設定(dbとcreate_appの定義)を行う。
- これにより、各ファイルでdbをインポートできるようになる。
- Blueprintでコントローラを分割し、コードの保守性を高める。

```./flask_app/__init__.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

def create_app():
    # appの設定
    app = Flask(__name__, instance_relative_config=True)
    app.config.from_pyfile('config.py')

    # DBの設定
    db.init_app(app)
    from flask_app import models

    # Blueprintの登録
    from flask_app.views.index import index_bp
    from flask_app.views.sample import sample_bp
    app.register_blueprint(index_bp)
    app.register_blueprint(sample_bp)

    return app
```

## app.py

\_\_init__.pyで定義したcreate_appからappを読み込む。
ここでBlueprintを登録しても動くが、create_appの中に書くのが一般的。

```./flask_app/app.py
from flask_app import create_app

app = create_app()

if __name__ == '__main__':
    app.run()
```

## models.py
データベースのテーブルを定義。
テーブルが増えてきたら、代わりにmodelsディレクトリを作成して、test.py, user.py, ... のように分けるとより良い。

```./flask_app/models.py
from flask_app import db


#TestDB
class Test(db.Model):
    __tablename__ = "test"
    id = db.Column(db.Integer, primary_key=True)
    hoge = db.Column(db.String(255))


#UserDB
class User(db.Model):
    __tablename__ = "user"
    id = db.Column(db.Integer, primary_key=True)
    user_name = db.Column(db.String(255), unique=True)
    password = db.Column(db.String(12))
```

## instanceフォルダ
機密性が高いファイルを格納する。
※.gitignoreに記載しないとpushされるので注意。

## config.py
appの設定を書く。
python_dotenvを使って、.envファイルから環境変数を読み込んでいる。

```./instance/config.py
import os
from dotenv import load_dotenv

load_dotenv() # load environment variables

SECRET_KEY = os.getenv("SECRET_KEY")
SQLALCHEMY_DATABASE_URI = os.getenv("DATABASE_URL")
```

## manage.py
データベースを作成する際に実行するファイル。
pythonの対話モードから作成する方法もあるが、一度書いてしまえばこっちの方が楽。

```./manage.py
from flask_app.app import app
from flask_app import db

with app.app_context():
    db.create_all()
```

## .envファイル
- 環境変数を定義する。
- FLASK_DEBUG=1はデバッグモードをON、0にするとOFFになる。
- SECRET_KEYには、安全性の高い文字列(パスワード)を入力する。

```./.env
FLASK_APP=flask_app.app
FLASK_DEBUG=1
DATABASE_URL="sqlite:///sampleDB.db"
SECRET_KEY="########################"
```

## 参考
https://msiz07-flask-docs-ja.readthedocs.io/ja/latest/patterns/appfactories.html
https://youtu.be/dam0GPOAvVI?si=t9KAntmqxlBKeJJz
https://ai-can-fly.hateblo.jp/entry/flask-directory-structure