当サイトは、アフィリエイト広告を利用しています
Pythonの軽量フレームワークであるFlask製のREST APIを
REST APIを効率的に実装するためのライブラリである「Flask-RESTful」を使って
実装をしたので基本をまとめておく。
APIを効率的に作成するためのライブラリ。
pipでインストールするだけで簡単に使うことができる
pip install flask flask_restful
簡単にFlask-RESTfulのメリットをまとめておく
Flask-RESTfulではREST APIでアクセスするリソースごとに
クラスを1:1で作成するため、APIの数が増えても管理しやすい
メソッド名がフレームワーク側でルール化されているので
コードが標準化できる
エラーハンドリングはフレームワークによって自動化され、
一貫したエラーレスポンスを生成できる
※要は書きやすい。
クライアントからのHTTPリクエストを解析し、必要なデータを取得・検証し、エラーハンドリングを行うことができる
※これはまだ正直、よくわかってないのでおいおい調べます。。。
Flask-RESTfulを使わないで、FlaskでREST APIを作る場合
のどちらかを使う。
関数ベースのルート、クラスベースのルートの実装については下記で
まとめています。
関数ベースのルートやクラスベースのルートの実装と比べると
Flask-RESTfulの方が書きやすく、コードも少なくなる。
実際にFlask-RESTfulを使ってREST APIを実装してみる
実装はdockerコンテナ上で行う。
ベースとして下記記事で作成、紹介しているREST APIをベースにする
環境やプロジェクト構成は上記と同じになるが
簡単に環境、構成、コンテナ作成関連ファイルを載せる
下記の環境で行う
Docker for Windowsのインストール方法については下記記事で 紹介しています
全体的な構成は下記のようになる
|-- .env|-- .vscode| |-- launch.json| `-- tasks.json|-- Dockerfile|-- api| |-- __init__.py| |-- api.py| `-- wsgi.py|-- docker-compose.yml|-- requirements.txt`-- vscode_ex_install.sh
基本的には同じだがflask_restfulをインストールして
それにあわせてソースを書き換えるため
は編集する。
※他は変わらない
dockerを使ってFlaskのREST APIを実装し、実行するための
コンテナを作成関連ファイル。
※docker composeで作成する
FLASK_APP=api.wsgi:api # Flaskがどのアプリケーションを実行するか指定(パッケージ.モジュール:flaskインスタンス)FLASK_ENV=development # Flaskがどの環境で動作するか指定FLASK_DEBUG=true #デバッグモードの指定
Flaskアプリケーションの設定や動作を制御するための環境変数を設定する
Pythonの環境をセットアップし、必要な依存関係をインストールするDockerイメージを作成する
FROM python:3.12# workspaceディレクトリ作成、移動WORKDIR /workspace# プロジェクトディレクトリにコピーCOPY requirements.txt /workspace# 必要モジュールのインストールRUN pip install --upgrade pipRUN pip install -r requirements.txt
requirements.txtを読み込み必要なパッケージをインストールする
version: "3"services:sample-api:container_name: "sample-api"build:context: .dockerfile: Dockerfileports:- "5000:5000"volumes:# バインドマウント- .:/workspace# 環境変数読み込みenv_file:- .envtty: true
コンテナ作成時に「flask_restful」をインストールするようにする
Flask==3.0.2flask_restful==0.3.10
関数ベースのルートとクラスベースのルートで書かれているapi.pyを
flask_restfulを使うversionに書き換える。
最初に全体のソースを載せる
詳細は後で解説する。
from flask import Flask, requestfrom flask_restful import Api, Resourceimport copy# flaskインスタンス作成api = Flask(__name__)# flask_restfulのApiインスタンス作成と関連づけflask_api = Api(api)# ディクショナリ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}]# flask_restfulのルーティングclass UserAPI(Resource):# 取得# HTTPリクエストにクエリパラメータあり# 全件取得 or ageフィルタリングdef get(self):age = request.args.get('age')if age:return list(filter(lambda user: user['age'] == int(age), users))return users# 登録# HTTPリクエストからJSONを受け取る# JSONデータを新規登録def post(self):data = request.get_json()res_users = copy.deepcopy(users)res_users.append(data)return res_users, 201# 更新# HTTPリクエストにパスパラメータあり# パスパラメータをkeyにしてJSONデータで更新def put(self, user_id):data = request.get_json()res_users = copy.deepcopy(users)res_users = list(map(lambda user: user.update(data) or user if user['user_id'] == user_id else user, res_users))return res_users# 削除# HTTPリクエストにパスパラメータあり# パスパラメータをkeyにして削除def delete(self, user_id):res_users = list(filter(lambda user: user['user_id'] != user_id, users))return res_users# エンドポイントとリソースクラスをマッピングするflask_api.add_resource(UserAPI, '/flaskRestful', endpoint='users')flask_api.add_resource(UserAPI, '/flaskRestful/<string:user_id>', endpoint='user')
flask_restfulを使うことで、効率的にREST APIの実装ができる。
詳細を解説する。
flask_restfulは下記の流れで実装する
# flaskインスタンス作成api = Flask(__name__)# flask_restfulのApiインスタンス作成と関連づけflask_api = Api(api)
Flask-RESTfulのApiインスタンスを作成する際にFlaskアプリケーションインスタンスを指定して
関連づける
エンドポイントとして動作するリソースを定義するために
Resourceクラスを継承したクラスを作成する
# flask_restfulのルーティングclass UserAPI(Resource):# 取得# HTTPリクエストにクエリパラメータあり# 全件取得 or ageフィルタリングdef get(self):age = request.args.get('age')if age:return list(filter(lambda user: user['age'] == int(age), users))return users# 登録# HTTPリクエストからJSONを受け取る# JSONデータを新規登録def post(self):data = request.get_json()res_users = copy.deepcopy(users)res_users.append(data)return res_users, 201# 更新# HTTPリクエストにパスパラメータあり# パスパラメータをkeyにしてJSONデータで更新def put(self, user_id):data = request.get_json()res_users = copy.deepcopy(users)res_users = list(map(lambda user: user.update(data) or user if user['user_id'] == user_id else user, res_users))return res_users# 削除# HTTPリクエストにパスパラメータあり# パスパラメータをkeyにして削除def delete(self, user_id):res_users = list(filter(lambda user: user['user_id'] != user_id, users))return res_users
各メソッドは、HTTPメソッド(GET、POST、PUT、DELETEなど)に対応し
そのメソッドが呼び出されるとリクエストに応じた処理を行う
Flask-RESTfulでは、デフォルトでリソースクラスのメソッド名がHTTPメソッド名と対応している。つまり
などのメソッド名が予約されているため
これらのメソッド名を変更すると、Flask-RESTfulは対応するHTTPメソッドを見つけられないため
エラーが発生するので注意
api.add_resource()を使って、リソースクラスとエンドポイントのURLパターンを指定し、
リソースとエンドポイントを結びつけます。
そうすると、エンドポイントに対するHTTPリクエストは、
UserAPIクラスのメソッドで処理されるようになる。
# エンドポイントとリソースクラスをマッピングするflask_api.add_resource(UserAPI, '/flaskRestful', endpoint='users')flask_api.add_resource(UserAPI, '/flaskRestful/<string:user_id>', endpoint='user')
このREST APIの場合、エンドポイントは
の2つあるので、2つのエンドポイントを1つのリソースクラス(UserAPIクラス)にマッピングしている。
複数エンドポイントを同じリソースクラスにマッピングする場合は
endpointパラメータ(一意)をつけておかないと正しくルーティングできない。
endpointパラメータを使わない場合は下記の方法で書くこともできる。
flask_api.add_resource(UserAPI, '/flaskRestful','/flaskRestful/<string:user_id>')
エンドポイントとリソースクラスが1:1でマッピングできる場合は
endpointパラメータはなくてもいい
Flask-RESTfulライブラリを使う前はレスポンスを返す時に
下記のようにJSONに変換するたに「jsonify」を使用していた
# 取得# HTTPリクエストにクエリパラメータあり# 全件取得 or ageフィルタリングdef get(self):age = request.args.get('age')if age:return jsonify(list(filter(lambda user: user['age'] == int(age), users)))return jsonify(users)
Flask-RESTfulのResourceクラスは、デフォルトでPythonの辞書やリストをJSONに自動的に
変換しくれるので明示的に「jsonify」を使用する必要はない
flask_restfulを使ってREST APIを実装してみた。
実装したみた感想としては、flask_restfulがREST APIを効率的に
実装するためのライブラリだけあって、わかりやすい。
今回は基本的な実装のみになる。
flask_restfulには、まだ色々と使えそう機能(リクエスト解析)や
Blueprint併用してルートとまとめるなど便利な使い方ができそうなので
調べたらまとめたい。
「Flask-RESTfulのabort関数」の使い方については下記記事でまとめています