BlueprintでFlaskアプリケーションを分割する

Flaskでwebアプリケーションを作成していて機能が増えてくると、一つのapp.pyに記述するプログラムが長大になり、メンテナンス性が落ちてくるので、`Blueprint`というモジュールを使ってアプリケーションを分割します。

今回はCRUD（Create,Read,Update,Delete)の4つの機能に分かれたFlaskアプリケーションを例に、Blueprintを使ってアプリケーションを分割してみます。

## ディレクトリ構成
Blueprintを使う際のディレクトリ構成は、こんな感じです。
![directory.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2781928/57882dd0-b218-fbfa-b170-b9541f36033c.png)


「Create」「Read」「Update」「Delete」それぞれのディレクトリがあり、その中にそれぞれの機能を記載する`views.py`ファイルと、実際にレンダリングされるhtmlファイルが`templates`ディレクトリの中に入っているのがポイントです。

それら全ての機能が`app.py`に集約されてくる、というイメージです。
では、初めに`app.py`ファイルから書いていきます。

## app.pyのプログラム

```Python:app.py
from flask import Flask

def create_app():
    app = Flask(__name__)

    #createページ
    from create import views as create_views
    app.register_blueprint(create_views.create, url_prefix="/create")

    # その他のページも同様にimport
    return app
```

`app.py`の中で`create_app`関数を作成し、その中で各ディレクトリからインスタンスをimportしてきます。
importしてきたインスタンスをBlueprintの`register_blueprint`メソッドによってappに登録します。
（この時点では、各ディレクトリの`views.py`ファイルも`templates`も作成していないので、`flask run`してもエラーになります。）

次に、それぞれのディレクトリの`views.py`ファイルを作成します。

## 各ディレクトリの「views.py」を作成
最初に、`create`ディレクトリの`views.py`を作成します。

```Python:create/views.py
from flask import Blueprint, render_template

create = Blueprint(
    "create",
    __name__,
    template_folder="templates",
)

@create.route("/")
def index():
    # createルートの機能を記載
    return render_template("create/index.html")
```

Blueprintモジュールをimportし、`create`という名前でBlueprintクラスをインスタンス化します。（このインスタンスが先程`app.py`でimportしているインスタンスです。）

さらに、`/create`ルートでそれぞれの機能を実装し、ブラウザ上にレンダリングされるhtmlファイルを`render_template`関数で指定します。

## htmlファイルの作成
続いて、`/create`ルートでレンダリングされるhtmlファイルを`/create/templates/create/index.html`ファイルとして作成します。

ここで注意しなければならないのが、templatesディレクトリ配下にcreateディレクトリを一度挟むという点です。
（まどろっこしいのですが、こうしないとflaskが正しくパスを認識できずhtmlファイルがレンダリングされません・・・）

```html:/create/templates/create/index.html
<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="utf-8">
        <title>Create</title>
        <link rel="stylesheet" href="{{ url_for('static',filename='style.css') }}">
    </head>
    <body>
        <h1>Create</h1>
    </body>
</html>
```

 CSSでデザインを当てたい場合は、`static/css/style.css`ファイルにスタイルを記述し、
 `<link rel="stylesheet" href="{{ url_for('static',filename='style.css') }}">`
 で読み込みます。

 この状態で`flask run`してアプリケーションを起動し、ブラウザで
 `http://127.0.0.1:5000/create/`
 にアクセスすると、createページがレンダリングされます。

基本的な流れは以上です。
残りの`read`,`update`,`delete`ページも同様に`views.py`と`index.html`ファイルを編集していきます。

```Python:read/views.py
from flask import Blueprint, render_template

read = Blueprint(
    "read",
    __name__,
    template_folder="templates",
)

@read.route("/")
def index():
    # createルートの機能を記載
    return render_template("read/index.html")
```

```html:/read/templates/read/index.html
<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="utf-8">
        <title>Read</title>
        <link rel="stylesheet" href="{{ url_for('static',filename='style.css') }}">
    </head>
    <body>
        <h1>Read</h1>
    </body>
</html>
```

```Python:app.py
#以下を追加
#readページ
    from read import views as read_views
    app.register_blueprint(read_views.read, url_prefix="/read")
#その他のページも同様に
```

すべてのページを登録したら、`flask run`して

`http://127.0.0.1:5000/read/`
`http://127.0.0.1:5000/update/`
`http://127.0.0.1:5000/delete/`

それぞれのページが表示されれば、Blueprintでの分割完了です。