当サイトは、アフィリエイト広告を利用しています
flaskのREST APIを効率的に実装するためのライブラリである
「Flask-RESTful」のabort関数の使い方を調べたのでまとめておく
「Flask-RESTful」自体の使い方については下記記事でまとめています
abort
関数は、エラーメッセージとHTTPステータスコードをクライアントに返すための
Flask-RESTfulの組み込み関数
特定のHTTPステータスコードとともにエラーレスポンスを直ちに送信するために使う。
要は条件が満たされない場合(エラー)にリクエストを直ちに終了させることができる。
abort関数は
と2種類ある
今回はFlask-RESTfulのabort関数の使い方をまとめる
違いとしては、Flask-RESTfulのabort関数は
基本的にはflaskのabort関数と同じでHTTPエラーコードを指定してAPIエラーを発生させるために使用されるが
より詳細なエラーハンドリングやエラーメッセージのカスタマイズが可能で
エラーレスポンスをJSON形式で変えることができる
Flask-RESTfulを使う場合は、Flask-RESTfulのabort関数を使う方が
効率的に実装できる
abort関数はflaskのflask_restfulに含まれているため
pipでflaskとflask_restfulをインストールする必要がある
# インストールpip install flask flask_restful# 確認pip show flask flask_restfulName: FlaskVersion: 3.0.2Summary: A simple framework for building complex web applications.Home-page:Author:Author-email:License:Location: /usr/local/lib/python3.12/site-packagesRequires: blinker, click, itsdangerous, Jinja2, WerkzeugRequired-by: Flask-Cors, Flask-RESTful---Name: Flask-RESTfulVersion: 0.3.10Summary: Simple framework for creating REST APIsHome-page: https://www.github.com/flask-restful/flask-restful/Author: Twilio API TeamAuthor-email: help@twilio.comLicense: BSDLocation: /usr/local/lib/python3.12/site-packagesRequires: aniso8601, Flask, pytz, sixRequired-by:
abort関数はflask_restfulからimportして使う
そして、abort関数の基本構文は下記になる
from flask_restful import abortabort(400,status="404",message="not found",description="error")
上記のレスポンスは下記になる
{"status": "404","message": "not found","description": "error"}
後述するがこれは「カスタムメッセージ」という使い方になる
abort関数には下記の使い方ができる
それぞれの使い方を整理する
デフォルトとはabort関数の第一引数のみ設定して使う使い方
Flask-RESTfulの内部で定義されているデフォルトメッセージが表示される
from flask import Flask, requestfrom flask_restful import Api, Resource,abortimport 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:result = list(filter(lambda user: user['age'] == int(age), users))if result:return resultelse:abort(404)return users# エンドポイントを設定flask_api.add_resource(UserAPI, '/flaskRestful')
usersに存在しないage=99をクエリパラメータに指定してリクエストを送ると
デフォルトメッセージのみが返却される
{"message": "The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again."}
デフォルトとはabort関数の第一引数と第二引数以上を設定して使う使い方
from flask import Flask, requestfrom flask_restful import Api, Resource,abortimport 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:result = list(filter(lambda user: user['age'] == int(age), users))if result:return resultelse:abort(404, status=404, message=f'指定された年齢{age}歳のユーザーは存在しません',users=users)return users# エンドポイントを設定flask_api.add_resource(UserAPI, '/flaskRestful')
usersに存在しないage=99をクエリパラメータに指定してリクエストを送る
と第二以降で指定したものがJSON形式で返却される
{"status": 404,"message": "指定された年齢99歳のユーザーは存在しません","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}]}
エラーレスポンスの型が決まっているなら外部で定義した関数内で
abort関数を使ったほうが効率的になる
from flask import Flask, requestfrom flask_restful import Api, Resource,abortimport 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}]# エラー関数def make_error_message(code,status,message):abort(code, status=status,message=message)# flask_restfulのルーティングclass UserAPI(Resource):# 取得# HTTPリクエストにクエリパラメータあり# 全件取得 or ageフィルタリングdef get(self):age = request.args.get('age')if age:result = list(filter(lambda user: user['age'] == int(age), users))if result:return resultelse:make_error_message(404,status=404,message=f'指定された年齢{age}歳のユーザーは存在しません')return users# エンドポイントを設定flask_api.add_resource(UserAPI, '/flaskRestful')
usersに存在しないage=99をクエリパラメータに指定してリクエストを送ると
第二以降で指定したものがJSON形式で返却される
{"status": 404,"message": "指定された年齢99歳のユーザーは存在しません"}
カスタムエラーハンドリングにもう一パターンある
Flask-RESTfulの内部で定義されているデフォルトメッセージ自体を
上書きすることができる
from flask import Flask, requestfrom flask_restful import Api, Resource,abortimport copy# flaskインスタンス作成api = Flask(__name__)# デフォルト上書きerrors={"NotFound":{'message':'指定されたユーザーは存在しません','status':404},"Conflict":{'message':'重複しています','status':409}}# flask_restfulのApiインスタンス作成flask_api = Api(api,errors=errors)# ディクショナリ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:result = list(filter(lambda user: user['age'] == int(age), users))if result:return resultelse:abort(404)return users# エンドポイントを設定flask_api.add_resource(UserAPI, '/flaskRestful')
usersに存在しないage=99をクエリパラメータに指定してリクエストを送る
と上書きされたメッセージが表示される
{"message": "指定されたユーザーは存在しません","status": 404}
HTTPステータスコード名をキーにして紐づけているので、errorsディクショナリの「NotFound」が「Not Found」になってたりすると紐づけが失敗して
デフォルトメッセージがそのまま表示されるので注意
また一般的なHTTPステータスコード名の上書きしかできない
例えば下記のように自分で作ったカスタムメッセージなどは作ることができない
from flask import Flask, requestfrom flask_restful import Api, Resource,abortimport copy# flaskインスタンス作成api = Flask(__name__)# デフォルト上書きerrors={"NotFound":{'message':'指定されたユーザーは存在しません','status':404},"Conflict":{'message':'重複しています','status':409},"Error":{'message':'エラー','status':444}}# flask_restfulのApiインスタンス作成flask_api = Api(api,errors=errors)# ディクショナリ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:result = list(filter(lambda user: user['age'] == int(age), users))if result:return resultelse:abort(444)return users# エンドポイントを設定flask_api.add_resource(UserAPI, '/flaskRestful')
あくまで上書きできるだけ。
上書きしてしまうと他の場所で呼び出したabort(404)のレスポンスも全部それになってしまうので
正直あまり実用性はなさそう
flask_restfulのabort関数の使い方をまとめてみた。
基本的にはカスタムエラーハンドリングを使うことが多そう。