当サイトは、アフィリエイト広告を利用しています

【Flask】Flask-RESTfulでREST APIを実装する

作成日:2024月04月06日
更新日:2024年04月17日

Pythonの軽量フレームワークであるFlask製のREST APIを
REST APIを効率的に実装するためのライブラリである「Flask-RESTful」を使って
実装をしたので基本をまとめておく。

Flask-RESTfulとは?

APIを効率的に作成するためのライブラリ。
pipでインストールするだけで簡単に使うことができる

pip
pip install flask flask_restful

Flask-RESTfulのメリットは?

簡単にFlask-RESTfulのメリットをまとめておく

構造の明確化(メンテナンス性向上)

Flask-RESTfulではREST APIでアクセスするリソースごとに
クラスを1:1で作成するため、APIの数が増えても管理しやすい

コードの標準化

メソッド名がフレームワーク側でルール化されているので
コードが標準化できる

エラーハンドリング

エラーハンドリングはフレームワークによって自動化され、
一貫したエラーレスポンスを生成できる
※要は書きやすい。

リクエスト解析

クライアントからのHTTPリクエストを解析し、必要なデータを取得・検証し、エラーハンドリングを行うことができる
※これはまだ正直、よくわかってないのでおいおい調べます。。。

他の実装方法

Flask-RESTfulを使わないで、FlaskでREST APIを作る場合

  • 関数ベースのルート
  • クラスベースのルート

のどちらかを使う。

関数ベースのルート、クラスベースのルートの実装については下記で
まとめています。

関数ベースのルートやクラスベースのルートの実装と比べると
Flask-RESTfulの方が書きやすく、コードも少なくなる。

Flask-RESTfulを使う

実際にFlask-RESTfulを使ってREST APIを実装してみる
実装はdockerコンテナ上で行う。

ベースとして下記記事で作成、紹介しているREST APIをベースにする

環境やプロジェクト構成は上記と同じになるが
簡単に環境、構成、コンテナ作成関連ファイルを載せる

環境

下記の環境で行う

  • Windows10
  • Docker version 24.0.2(Docker for Windows)
  • VScode
  • Remote Development(VScodeの拡張機能)
  • Docker for Windows
  • Flask 3.0.2
  • flask_restful 0.3.10

Docker for Windowsのインストール方法については下記記事で 紹介しています

構成

全体的な構成は下記のようになる

bash
|-- .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をインストールして
それにあわせてソースを書き換えるため

  • requirements.txt
  • api.py

は編集する。
※他は変わらない

コンテナ作成ファイル

dockerを使ってFlaskのREST APIを実装し、実行するための
コンテナを作成関連ファイル。
※docker composeで作成する

.env

.env
FLASK_APP=api.wsgi:api # Flaskがどのアプリケーションを実行するか指定(パッケージ.モジュール:flaskインスタンス)
FLASK_ENV=development # Flaskがどの環境で動作するか指定
FLASK_DEBUG=true #デバッグモードの指定

Flaskアプリケーションの設定や動作を制御するための環境変数を設定する

Dockerfile

Pythonの環境をセットアップし、必要な依存関係をインストールするDockerイメージを作成する

Dockerfile
FROM python:3.12
# workspaceディレクトリ作成、移動
WORKDIR /workspace
# プロジェクトディレクトリにコピー
COPY requirements.txt /workspace
# 必要モジュールのインストール
RUN pip install --upgrade pip
RUN pip install -r requirements.txt

requirements.txtを読み込み必要なパッケージをインストールする

docker-compose.yml

docker-compose.yml
version: "3"
services:
sample-api:
container_name: "sample-api"
build:
context: .
dockerfile: Dockerfile
ports:
- "5000:5000"
volumes:
# バインドマウント
- .:/workspace
# 環境変数読み込み
env_file:
- .env
tty: true
  • DockerfileをbuildしたDockerイメージを元にコンテナを作成
  • volumeはバインドマウントにする
  • 環境変数を.envから読み込み設定する

requirements.txt

コンテナ作成時に「flask_restful」をインストールするようにする

requirements.txt
Flask==3.0.2
flask_restful==0.3.10

flask_restfulをapi.pyで実装

関数ベースのルートとクラスベースのルートで書かれているapi.pyを
flask_restfulを使うversionに書き換える。

最初に全体のソースを載せる
詳細は後で解説する。

api.py
from flask import Flask, request
from flask_restful import Api, Resource
import 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_restfulは下記の流れで実装する

  • flask_restfulのApiインスタンス作成とflaskインスタンスとの関連づけ
  • Resourceクラスを継承したクラスを作る
  • エンドポイントとリソースクラスをマッピングする

flask_restfulのApiインスタンス作成とflaskインスタンスとの関連づけ

Apiインスタンス作成
# flaskインスタンス作成
api = Flask(__name__)
# flask_restfulのApiインスタンス作成と関連づけ
flask_api = Api(api)

Flask-RESTfulのApiインスタンスを作成する際にFlaskアプリケーションインスタンスを指定して
関連づける

Resourceクラスを継承したクラスを作る

エンドポイントとして動作するリソースを定義するために
Resourceクラスを継承したクラスを作成する

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など)に対応し
そのメソッドが呼び出されるとリクエストに応じた処理を行う

エンドポイントとリソースクラスをマッピングする

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の場合、エンドポイントは

  • '/flaskRestful'
  • '/flaskRestful/<string:user_id>'

の2つあるので、2つのエンドポイントを1つのリソースクラス(UserAPIクラス)にマッピングしている。

複数エンドポイントを同じリソースクラスにマッピングする場合は
endpointパラメータ(一意)をつけておかないと正しくルーティングできない。

endpointパラメータを使わない場合は下記の方法で書くこともできる。

マッピングパターン
flask_api.add_resource(UserAPI, '/flaskRestful','/flaskRestful/<string:user_id>')

エンドポイントとリソースクラスが1:1でマッピングできる場合は
endpointパラメータはなくてもいい

jsonifyについて

Flask-RESTfulライブラリを使う前はレスポンスを返す時に
下記のようにJSONに変換するたに「jsonify」を使用していた

response
# 取得
# 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関数」の使い方については下記記事でまとめています

参考

新着記事

タグ別一覧
top