Как заставить Flask_restplus использовать обработчики ошибок из app_errorhandler? - PullRequest
0 голосов
/ 15 декабря 2018

Я пытаюсь использовать глобальные обработчики ошибок (app_errorhandler) в своих API, но у меня возникают некоторые проблемы.У меня есть план для ошибок, где я определяю глобальные ошибки, определенные как:

from werkzeug.exceptions import NotFound
from flask_app.errors import error_bp

@error_bp.app_errorhandler(NotFound)
def not_found_error(error):
    return "Error 404", 404

, и это прекрасно работает для всех маршрутов приложения, но не для API, созданных flask_restplus или flask_restful (пробовал оба).Когда я пытаюсь поднять в них NotFound, я получаю:

"Запрошенный URL-адрес не найден на сервере. Если вы ввели URL-адрес вручную, проверьте правильность написания и повторите попытку. Вы запросилиэтот URI [/ user / info / 1 /], но вы имели в виду / user / info // или / user / edit // или / user / login? "

Когда я определяю errorhandler в моем API как:

@user_api.errorhandler(NotFound)
def new_error(error):
    return "Error handler in API 404"

Он не использует этот errorhandler в API, но глобальный (почему? как?), поэтому я получил способ использовать app_errorhandler, но это не такрешение, так как я не хочу определять для каждого API errorhandler, если у меня глобальная настройка.Все мои API созданы с использованием схемы, в которой они находятся.

Итак, мой вопрос: как использовать app_errorhandler в API без определения errorhandler в каждом API?

Ответы могутбыть flask_restplus или flask_restful, потому что у меня нет проблем с переключением с одного на другой.Заранее спасибо.

ПРИМЕЧАНИЕ: Есть много обходных путей, но я думаю, что api s должен иметь возможность использовать app s ошибки по умолчанию, потому что blueprints может использоватьони и api s наследуют чертежи

Структура и код проекта согласно Mehdi Sadeghi запросу:

.
|____flask_test_app
| |____errors
|   |___ __init__.py
|   |___ handlers.py
| |____test_found
|   |___ __init__.py
|   |___ apis.py
| |_____ __init__.py

__init__.py:

from flask import Flask

def create_app(config_name):
    app = Flask(__name__)
    app.config.from_object(config_name)

    from .errors import error_bp
    app.register_blueprint(error_bp)

    from .test_found import test_found
    app.register_blueprint(test_found)

    return app

errors.__init__.py:

from flask import Blueprint
error_bp = Blueprint('error_bp', import_name='error_bp')

from flask_test_app.errors import handlers

errors.handlers.py:

from werkzeug.exceptions import NotFound
from flask_test_app.errors import error_bp

@error_bp.app_errorhandler(NotFound)
def not_found_error(error):
    return "Error 404", 404

test_found.__init__py:

from flask import Blueprint
from flask_restplus import Api

test_found = Blueprint('test_found', import_name='test_found',
                       url_prefix='/test_found')

test_found_api = Api(test_found)
from flask_test_app.test_found import apis

test_found.apis.py:

from flask_restplus import Resource
from flask_test_app.test_found import test_found, test_found_api
from werkzeug.exceptions import NotFound

@test_found.route('/test_not_found', methods=['GET'])
def test_not_found():
    raise NotFound
    return "Not found does not work"

class TestAPINotFound(Resource):
    def get(self):
        raise NotFound
        return "TEST NOT FOUND FOR APIs"

test_found_api.add_resource(TestAPINotFound,
                      '/test_api_not_found',
                      endpoint='user_test')

1 Ответ

0 голосов
/ 17 декабря 2018

В фляге-restful, как описано в документах , вы можете передать словарь errors в API и настроить возвращаемое сообщение:

errors = {
    'NotFound': {
        'message': "Something is missing.",
        'status': 404,
    }
}

api = Api(app, errors=errors)

Более того, он обеспечивает flask_restful.abort что вы можете использовать в любом месте вашего API:

class HelloWorld(Resource):
    def get(self):
        if not self.has_permission():
            return flask_restful.abort(403)
        return {'hello': 'world'}

Вы также можете перехватывать ваши исключения, такие как NotFound и использовать flask_restful.abort, как указано выше.

Однако, если вам действительно нужночтобы настроить обработку ошибок, вы можете создать подкласс Api и реализовать собственную обработку ошибок перед вызовом flask_restful.abort:

class CustomApi(Api):
    def handle_error(self, e):
        # Do something and then abort
        flask_restful.abort('some error code...', 'error message')

api = CustomApi(app, errors=errors)
...