flask Blueprintを理解したい。

# app.routeという前提
そもそもこの`blueprint`という機能に関して調べるきっかけとなったのはflaskに記述のある`app.route`という部分が`blueprint.route`と記載されていたことです。
そして自分は初学者であるため、app.routeとはflaskにおいて何をしている箇所であるか、しっかりと説明することはできそうになかったため、ここから勉強です。

ということで以下の記事を参考に、flaskの基礎から学びます。

https://qiita.com/massa-potato/items/2c4c3e0f459b2bc4c7ee

## flaskの基本構造

```python
#①モジュールのインポート
from flask import Flask 

#②Webアプリ作成
app = Flask(__name__) 

#③エンドポイント設定（ルーティング）
@app.route('/')
def hello():
    return 'Hello World!'

 #④Webアプリ起動~~~~
if __name__ == '__main__':
    app.run(debug=True)
```

まぁ普段はなんとなくここから切りはりして実装していたわけですが、分割すると以下のような機能に分かれるそうです。

### 1.モジュールのインポート
```python
from flask import Flask
```
ここは良いですね。flaskモジュールのFlaskクラスをインポートしています。

### 2.Webアプリ作成
```python
app = Flask(__name__)
```

appに対してflaskクラスのインスタンスを代入しており、今後`app.route()`等でルーティングを定義するなど、さまざまな操作を行います。

### 3.エンドポイント設定
さてここが問題のポイントです。
```python
@app.route('/')
def hello():
    return 'Hello World!'
```

ここでルーティングが定義されているそうです。
さて、引用元の記事で詳しく説明してもらえているので、シンプルにしますね。
ズバリ、`/　にアクセスしたときの処理をappに対して登録している`ということみたいです。
とってもざっくりですが、このようなシンプルな記述でそれが実現できているようです。

しかし私はよくわかっていない箇所を見つけました。
＠app.touteの`@`ってなんですか。
てっきりflask特有の記述かなとか感じておりましたが、どうやら`デコレータ`というPythonの文法だそうです。

## デコレータ
https://qiita.com/Kuroi_Cc/items/c250a93e043aa1f6a84d

まぁ私がわかりやすい説明をするよりも、別の方がとってもわかりやすく解説してくださっているのはいつものことなのですが、勉強のために一度文章化します。

とってもシンプルな表現をするとすれば、デコレータによって`関数の「前処理」と「後処理」を行うことができる`というようなものらしいです。

```python
def decorator(func):
    def wrapper():
        print("デコレータをつけられた関数の前処理をしました。")

        func()

        print("デコレータをつけられた関数の後処理をしました。")

    return wrapper

@decorator
def function():
    print("私がデコレータをつけられた関数です。")

function()
```

このように記載をすると、以下のような実行結果が得られます。

```
デコレータをつけられた関数の前処理をしました。
私がデコレータをつけられた関数です。
デコレータをつけられた関数の後処理をしました。
```

`function()` を実行すると、デコレータがついているため、`decorator()`が先に処理され、内部で前処理と後処理が行われています。

私が理解しやすいなと感じた表現は`関数自身が、他の関数に自分自身を引数として渡している`というものである。

何を言っているかわからないと思うが、以下の通り＠をつけずに記載するとわかる人も多くなるのではないだろうか。

```python
def decorator(func):
    def wrapper():
        print("デコレータをつけられた関数の前処理をしました。")

        func()

        print("デコレータをつけられた関数の後処理をしました。")

    return wrapper

def function():
    print("私がデコレータをつけられた関数です。")

function = decorator(function)

function()
```

得られる結果は＠のついた実装と同様になります。

重要なのは`function = decorator(function)`の部分です。
関数に関数自身を受け渡し、結果が返ってくるということだと理解しました。

## flaskでのデコレータ

```python
@app.route('/') 
def hello():
    return 'Hello World!'
```
さて、flaskの話に戻りますが上記デコレータに関して理解した後ならば、割とすんなりと理解できるのではないでしょうか。

app.route()に対して、「/」というURLにアクセスした際にhello()の内容を紐づけさせている。
つまり「/」というURLにアクセスした際にhello()をflaskによって適切に扱えるよう処理させているということです。

なんだか謎が解けてスッキリした気もしますね。

# やっとこさBlueprint

はい、やっとblueprintです。
そもそも私はflask-adminlteをいじっている時にこちらに遭遇しました。

https://github.com/app-generator/flask-adminlte

ということでどのような記述がされていたかというと、
```python
from apps.home import blueprint
from flask import render_template, request
from flask_login import login_required
from jinja2 import TemplateNotFound


@blueprint.route('/index')
@login_required
def index():

    return render_template('home/index.html', segment='index')
```

なんとなーくデコレータ部分がappからblueprintに置き換わっているのかなということはわかるかと思います。

手っ取り早く公式ドキュメントに目を通します。

https://msiz07-flask-docs-ja.readthedocs.io/ja/latest/blueprints.html

まぁ言っていることをすごくざっくりまとめると、大規模な構成になったときに「分割して実装することができる便利なもの」的な印象を受けました。
と、わかったような口ぶりで言いましたが、すごくふわふわして気持ち悪いですので以下の記事を参考に理解を深めます。

https://hogetech.info/programming/python/flask-blueprint

なるほど、そもそも開発をする上でコードを分割するという「わかりやすさ」がこの機能の特徴のようです。
という理解ができるまで苦労していたのですが、以下の記事でもう少し理解が進みました。

https://tma15.github.io/blog/2020/03/22/flask-blueprint%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%9F%E3%82%A2%E3%83%97%E3%83%AA%E9%96%8B%E7%99%BA%E3%81%AE%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88/

この記事から分かる通り、blueprintを二つ作ったとしたらページのURLは
- hogehoge/blueprint1
- hogehoge/blueprint2

となりますし、その下に続ければ

- hogehoge/blueprint1/page1
- hogehoge/blueprint1/page2
- hogehoge/blueprint2/page1
- hogehoge/blueprint2/page2

と全て異なるページが作成されるわけですね。

ということで今回の例を見てみましょう。

```python:routes.py
from apps.home import blueprint
from flask import render_template, request
from flask_login import login_required
from jinja2 import TemplateNotFound


@blueprint.route('/index')
@login_required
def index():

    return render_template('home/index.html', segment='index')
```

どうやらBlueprintはappsディレクトリ直下のhome/init.pyに記載されていそうです。

```python:home/__init__.py
from flask import Blueprint

blueprint = Blueprint(
    'home_blueprint',
    __name__,
    url_prefix=''
)
```

はい、先ほどの内容を理解した後ならば理解ができそうな内容ですね。
この例で言えば、indexに辿り着くにはhome_blueprintの下に入り込む必要があるということすなわち
`hogehoge/home_blueprint/index.html`
に辿り着けそうです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3403549/87bbdc0a-8761-fa65-0c4c-6dc1c28777bc.png)

はい、辿り着けませんでした。

ここで公式ドキュメントに戻ります。

>@simple_page.routeデコレータを利用して関数を結び付け（bind）するとき、blueprintは、後で（blueprintがFlaskインスタンスに）登録されるときにはshow関数をアプリケーション（Flaskインスタンス）へ登録するという意図を記録しておきます。さらに、blueprintは関数のエンドポイントの先頭へ、Blueprintクラスのコンストラクタで与えられたblueprintの名前（この例ではsimple_page）を付加します。blueprintの名前は、URLは変更せず、エンドポイントだけを変更します（訳注: ここでは、simple_page.showのように、エンドポイントの最初にはblueprint名を付け、対応するURLパスの「'/'」や「'/<paga>'」の最初にはblueprint名を付けないでURLルールでの対応付けが作成される、という意味合い）。

重要なのは`blueprintの名前はURLは変更せず、エンドポイントだけ変更する。`ということです。
要するに先ほど分かった気になっていた

>この記事から分かる通り、blueprintを二つ作ったとしたらページのURLは
>- hogehoge/blueprint1
>- hogehoge/blueprint2
>
>となりますし、その下に続ければ
>
>- hogehoge/blueprint1/page1
>- hogehoge/blueprint1/page2
>- hogehoge/blueprint2/page1
>- hogehoge/blueprint2/page2
>
>と全て異なるページが作成されるわけですね。

という箇所の解釈は間違っていたわけです。
要するにblueprintを抜いたエンドポイントのみをURLに入れれば良いわけですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3403549/247065bb-aea7-6bd4-1373-5e574c3b6893.png)

はい、成功したわけですね。
これは確かに開発段階では機能ごと、ページごとにどのようなルーティングをするのか、ファイルを分けることができ、実際にページが動作するときはユーザー側からは全く平常動作に見えるわけですね。

どのような目的を持った機能なのかが理解できればなんら難しいことはなく、理にかなった仕組みでした。

## 一文でまとめると

### URLは変えず、コードを分割して開発が楽になる仕組み。それがBlueprint。