web-dev-qa-db-ja.com

フラスコ休息のカスタムエラーメッセージjsonオブジェクト

次のようなabort()メソッドを使用すると、フラスコ・レストフルのエラー・メッセージをクライアントに簡単に伝搬できます。

abort(500, message="Fatal error: Pizza the Hutt was found dead earlier today
in the back seat of his stretched limo. Evidently, the notorious gangster
became locked in his car and ate himself to death.")

これにより、次のjson出力が生成されます

{
  "message": "Fatal error: Pizza the Hutt was found dead earlier today
       in the back seat of his stretched limo. Evidently, the notorious gangster
       became locked in his car and ate himself to death.", 
  "status": 500
}

追加のメンバーでjson出力をカスタマイズする方法はありますか?例えば:

{
  "sub_code": 42,
  "action": "redirect:#/Outer/Space"
  "message": "You idiots! These are not them! You've captured their stunt doubles!", 
  "status": 500
}
22
Derek

人々はabort()を使いすぎる傾向がありますが、実際には、独自のエラーを生成するのは非常に簡単です。カスタムエラーを簡単に生成する関数を作成できます。JSONに一致する関数を次に示します。

_def make_error(status_code, sub_code, message, action):
    response = jsonify({
        'status': status_code,
        'sub_code': sub_code,
        'message': message,
        'action': action
    })
    response.status_code = status_code
    return response
_

次に、abort()を呼び出す代わりに、次のようにします。

_@route('/')
def my_view_function():
    # ...
    if need_to_return_error:
        return make_error(500, 42, 'You idiots!...', 'redirect...')
    # ...
_
35
Miguel

@dappiuについてコメントする50の評判がないので、新しい回答を書く必要がありますが、それは本当にに関連しています "Flask-RESTfulは、よりクリーンな方法で処理できますエラー "として 非常に不十分にここに文書化

使い方がわからなくなってしまったのが悪い文書です。重要なのは、カスタム例外がフラスコ_レストフルインポートHTTPExceptionを継承する必要があることです。 Python Exceptionは使用できません。

from flask_restful import HTTPException

class UserAlreadyExistsError(HTTPException):
    pass

custom_errors = {
    'UserAlreadyExistsError': {
        'message': "A user with that username already exists.",
        'status': 409,
    }
}

api = Api(app, errors=custom_errors)

Flask-RESTfulチームはカスタム例外処理を簡単にするために良い仕事をしましたが、ドキュメントは努力を台無しにしました。

24
Crespo Wang

@Miguelのコードは、ほとんどの場合に使用する必要があります。例外は使用せず、要求ハンドラのブランチで応答を返すだけです。ただし、例外を発生させるアボートメカニズムが本当に必要な場合(これは、フィルターメソッドなどで役立つ場合があります)、 flask.abortResponse オブジェクトを受け入れることに注意してください(これをチェックしてください 要点 ):

from flask import abort, make_response, jsonify

response = make_response(jsonify(message="Message goes here"), 400)
abort(response)
7
tokland

このカスタムエラー処理を適切に機能させるには、サブクラス化されたcodeに属性HttpExceptionを定義する必要がありました。

from werkzeug.exceptions import HTTPException
from flask_restful import Api
from flask import Blueprint

api_bp = Blueprint('api',__name__)

class ResourceAlreadyExists(HTTPException):
    code = 400

errors = {
    'ResourceAlreadyExists': {
        'message': "This resource already exists.",
        'status': 409,
    },
}

api = Api(api_bp, errors=errors)

その後、例外を発生させます

raise ResourceAlreadyExists
3
Crispin

これは本当にシンプルでクリーンな基本機能です。これは@Miguelに似ていますが、あまり専門的ではなく、Flaskの意図するabort()の使用と一貫性があります。制御フローに例外を使用することは、Python)のアンチパターンではなく、実際に推奨されます。したがって、例外を返すのではなく、発生させることが最も一般的な方法であると主張することができます。フレームワークはそれらのための偶然性を持っています。

 def json_abort(status_code, data=None):
    if data is None:
        data = {}
    response = jsonify(data)
    response.status_code = status_code
    abort(response)

# then somewhere in your app during a request
json_abort(404, {'error': 'Not Found'}) 

今、あなたはそれを好きなように拡張してカスタマイズすることができます。

1
Michael Ekoka

それは明らかに遅いですが、その間、Flask-RESTfulは docs で指摘されているように、エラーを処理するためのより明確な方法を提供することができました。

また、改善が役立つことを示唆するために開かれた issue も開きます。

1
dappiu