当サイトは、アフィリエイト広告を利用しています
FlaskのBlueprintを使ってREST APIのリソースごとに
ルーティングを整理したので使い方を忘備録として残す
Blueprintを使ったルーティング整理は
でそれぞれ実装してみる
FlaskのBlueprintは、アプリケーションの機能を複数のファイル(モジュール)に分割するための機能。
FlaskでREST APIをつくるとき、リソースごとにルーティングを分割して整理することができる
実際にBlueprintを使って通常FlaskREST APIのルーティングをリソースごとに
分割して整理してみる
Flask製のREST APIをdockerコンテナを使って作る方法については
下記で詳しくまとめている
pipでflaskをインストールしていれば使うことができる
pip install flask
usersとbooksのリソースに対しての簡単なREST APIを作る
ディレクトリ構成は下記になる
.├── api│ └── api.py
現状ではリソースごとに分割されていない
from flask import Flask# flaskインスタンス作成api = Flask(__name__)# usersリソースusers = [{"user_id": "1", "name": "tujimura", "age": 11},{"user_id": "2", "name": "mori", "age": 20},{"user_id": "3", "name": "shimada", "age": 50},{"user_id": "4", "name": "kyogoku", "age": 70}]# booksリソースbooks = [{"book_id": "1", "book_name": "凍りのクジラ"},{"book_id": "2", "book_name": "全てがFになる"},{"book_id": "3", "book_name": "占星術殺人事件"},{"book_id": "4", "book_name": "姑獲鳥の夏"}]# usersルーティング@api.route('/users', methods=['GET'])def get_users():# 取得return users# booksルーティング@api.route('/books', methods=['GET'])def get_books():# 取得return books
このぐらいなら問題ないが、リソースが増えて、エンドポイントも
増えていくとややこしくなるので、リソースごとにblueprintを
使って分割してみる
下記のような構成にする
.├── api│ ├── api.py│ └── api_resource│ ├── __init___.py│ ├── booksAPI.py│ └── userAPI.py
api_resourceを作成し、その配下にリソースごとのファイル
を作成する
api_resourceをパッケージとして認識させるため
init_.pyも作成する※中身は空でOK
またapi.pyも中身は変更する
usersリソースに対するルーティングをbluprintでファイル分割して
切り出す
from flask import Blueprint# blueprintインスタンス作成(users)bp = Blueprint('users', __name__)# usersリソースusers = [{"user_id": "1", "name": "tujimura", "age": 11},{"user_id": "2", "name": "mori", "age": 20},{"user_id": "3", "name": "shimada", "age": 50},{"user_id": "4", "name": "kyogoku", "age": 70}]# usersルーティング@bp.route('/users', methods=['GET'])def get_users():# 取得return users
booksリソースに対するルーティングをbluprintでファイル分割して
切り出す
from flask import Blueprintfrom flask_restful import Api, Resource# blueprintインスタンス作成(books)bp = Blueprint('books', __name__)# booksリソースbooks = [{"book_id": "1", "book_name": "凍りのクジラ"},{"book_id": "2", "book_name": "全てがFになる"},{"book_id": "3", "book_name": "占星術殺人事件"},{"book_id": "4", "book_name": "姑獲鳥の夏"}]# booksルーティング@bp.route('/books', methods=['GET'])def get_books():# 取得return books
Blueprint使う時は最初に下記のようにblueprintインスタンスを生成する
bp = Blueprint('users', __name__)
第一引数はBlueprintの名前を指定する
これはFlaskアプリケーション内でBlueprintを一意に識別するために
使用されるため他のBlueprintインスタンスと重複させるとエラーになる
お決まりのパターン。
余程、特殊な場合でないname以外を設定することはない
api.pyではリソースを分割して作成したblueprintインスタンスをimportして
flaskインスタンスに登録する
from flask import Flaskfrom api.api_resource import userAPIfrom api.api_resource import booksAPI# flaskインスタンス作成api = Flask(__name__)# flaskインスタンスにblueprintインスタンスを登録api.register_blueprint(userAPI.bp, url_prefix = '/api')api.register_blueprint(booksAPI.bp, url_prefix = '/api')if __name__ == "__main__":# flaskサーバーを起動api.run()
register_blueprintでは
を設定する
エンドポイントは、この場合はそれぞれ
になる
※ドメインとポートは除く。例えばローカル起動してる場合だと「localhost:5000/」になる
REST APIを効率的に実装するためのライブラリである「Flask-RESTful」を使って
作られたREST APIをBlueprintを使ってファイル分割し、ルーティングを整理する
※Blueprintのインストール方法は同じのため割愛する
flask_restfulについて下記記事で詳しくまとめています
usersとbooksのリソースに対してのflask_restfulで簡単なREST APIを作る
ディレクトリ構成は下記になる
.├── api│ └── api.py
リソースごとに分割されていない
from flask import Flaskfrom flask_restful import Api, Resource# flaskインスタンス作成api = Flask(__name__)# flask_restfulのApiインスタンス作成flask_api = Api(api)# usersリソースusers = [{"user_id": "1", "name": "tujimura", "age": 11},{"user_id": "2", "name": "mori", "age": 20},{"user_id": "3", "name": "shimada", "age": 50},{"user_id": "4", "name": "kyogoku", "age": 70}]# booksリソースbooks = [{"book_id": "1", "book_name": "凍りのクジラ"},{"book_id": "2", "book_name": "全てがFになる"},{"book_id": "3", "book_name": "占星術殺人事件"},{"book_id": "4", "book_name": "姑獲鳥の夏"}]# usersルーティングclass UserAPI(Resource):# 取得def get(self):return users# booksルーティングclass BooksAPI(Resource):# 取得def get(self):return books# エンドポイントを設定flask_api.add_resource(UserAPI, '/users')flask_api.add_resource(BooksAPI, '/books')
下記のような構成にする
.├── api│ ├── api.py│ └── api_resource│ ├── __init___.py│ ├── booksAPI.py│ └── userAPI.py
api_resourceを作成し、その配下にリソースごとのファイル
を作成する
api_resourceをパッケージとして認識させるため
init_.pyも作成する※中身は空でOK
またapi.pyも中身は変更する
ここまでは、ほぼ通常のFlaskのREST APIでBlueprintを使う場合と同じ
usersリソースに対するルーティングをbluprintでファイル分割して
切り出す
from flask import Blueprintfrom flask_restful import Api, Resource# blueprintインスタンス作成(users)bp = Blueprint('users', __name__)# flask_restfulのApiインスタンス作成# blueprintインスタンスを紐づけるflask_api = Api(bp)# usersリソースusers = [{"user_id": "1", "name": "tujimura", "age": 11},{"user_id": "2", "name": "mori", "age": 20},{"user_id": "3", "name": "shimada", "age": 50},{"user_id": "4", "name": "kyogoku", "age": 70}]# usersルーティングclass UserAPI(Resource):# 取得def get(self):return users# エンドポイントを設定flask_api.add_resource(UserAPI, '/users')
booksリソースに対するルーティングをbluprintでファイル分割して
切り出す
from flask import Blueprintfrom flask_restful import Api, Resource# blueprintインスタンス作成(books)bp = Blueprint('books', __name__)# flask_restfulのApiインスタンス作成# blueprintインスタンスを紐づけるflask_api = Api(bp)# booksリソースbooks = [{"book_id": "1", "book_name": "凍りのクジラ"},{"book_id": "2", "book_name": "全てがFになる"},{"book_id": "3", "book_name": "占星術殺人事件"},{"book_id": "4", "book_name": "姑獲鳥の夏"}]# booksルーティングclass BooksAPI(Resource):# 取得def get(self):return books# エンドポイントを設定flask_api.add_resource(BooksAPI, '/books')
api.pyではリソースを分割して作成したblueprintインスタンスをimportして
flaskインスタンスに登録する
from flask import Flaskfrom api.api_resource import userAPIfrom api.api_resource import booksAPI# flaskインスタンス作成api = Flask(__name__)api.register_blueprint(userAPI.bp, url_prefix = '/api')api.register_blueprint(booksAPI.bp, url_prefix = '/api')if __name__ == "__main__":# flaskサーバーを起動api.run()
通常のFlaskで作ったREST APIではblueprintインスタンス内でルーティングを行っていたため
flaskインスタンスにblueprintインスタンスを紐づけるだけでよかった。
下記のようなイメージ
── flaskインスタンス├── blueprintインスタンス(users)└── blueprintインスタンス(books)
flask_restfulの場合はルーティングを行っているのは
flask_restfulのApiインスタンスであるため、flaskインスタンスとApiインスタンスは
blueprintインスタンスを介して紐づけている
下記のようなイメージ
── flaskインスタンス├── blueprintインスタンス(users) ── Apiインスタンス(users)└── blueprintインスタンス(books) ── Apiインスタンス(books)
blueprintの使い方をREST APIをサンプルにして
まとめてみた。
分割後にディレクトリ構造についてはわかりやすいように
作ったのでプロジェクトやリソースの数によって適宜、調整する必要がある。