Проблема с декоратором Flask JWT вне контекста приложения

#python #flask #jwt

#python #flask #jwt

Вопрос:

Я довольно новичок в приложениях Flask. Хотя мое приложение работает для всех конечных точек, как и ожидалось, когда я попытался добавить авторизацию jwt, я столкнулся с этой проблемой. Я попробовал это решение app.app_context().push () на основе некоторых других опубликованных вопросов.

Любая помощь будет с благодарностью принята. Я также хотел бы использовать декоратор в нескольких API, должен ли я включать функцию token_required в каждый из них, или наилучшей практикой было бы импортировать?

Ошибка:

 Traceback (most recent call last):
  File "C:/Users/Gerasimos/Documents/Python/api_mongo/main.py", line 1, in <module>
    from app import create_app
  File "C:UsersGerasimosDocumentsPythonapi_mongoapp.py", line 2, in <module>
    from users.api import users
  File "C:UsersGerasimosDocumentsPythonapi_mongousersapi.py", line 60, in <module>
    @token_required
  File "C:UsersGerasimosDocumentsPythonapi_mongousersapi.py", line 31, in token_required
    return decorated()
  File "C:UsersGerasimosDocumentsPythonapi_mongousersapi.py", line 29, in decorated
    return jsonify({'message' : 'Token is invalid!'}), 401
  File "C:UsersGerasimosAppDataLocalProgramsPythonPython37-32libsite-packagesflaskjson__init__.py", line 309, in jsonify
    if current_app.config['JSONIFY_PRETTYPRINT_REGULAR'] or current_app.debug:
  File "C:UsersGerasimosAppDataLocalProgramsPythonPython37-32libsite-packageswerkzeuglocal.py", line 347, in __getattr__
    return getattr(self._get_current_object(), name)
  File "C:UsersGerasimosAppDataLocalProgramsPythonPython37-32libsite-packageswerkzeuglocal.py", line 306, in _get_current_object
    return self.__local()
  File "C:UsersGerasimosAppDataLocalProgramsPythonPython37-32libsite-packagesflaskglobals.py", line 51, in _find_app
    raise RuntimeError(_app_ctx_err_msg)
RuntimeError: Working outside of application context.

This typically means that you attempted to use functionality that needed
to interface with the current application object in some way. To solve
this, set up an application context with app.app_context().  See the
documentation for more information.
 

Моя структура приложения:

main.py

 from app import create_app

app = create_app()

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)
 

app.py

 from flask import Flask
from users.api import users
from auth.api import auth


def create_app(settings_overrides=None):
    app = Flask(__name__)
    configure_settings(app, settings_overrides)
    configure_blueprints(app)
    return app


def configure_settings(app, settings_override):
    app.config.update({
        'DEBUG': True,
        'TESTING': True,
        'JSON_SORT_KEYS': False
    })
    if settings_override:
        app.config.update(settings_override)


def configure_blueprints(app):
    app.register_blueprint(users, url_prefix='/api')
    app.register_blueprint(auth, url_prefix='/api')
 

usersapi.py

 from flask import Blueprint, request, Response, jsonify
from pymongo import MongoClient
import json
from validation.RegistrationValidator import UserSchema
from validation.UpdateUserValidator import UpdateUserSchema
from marshmallow import ValidationError
from functools import wraps
import jwt

client = MongoClient('localhost', 27017)
database = client['python_crud_api']
users_collection = database['users']

users = Blueprint('users', __name__)

SECRET_KEY = "hrtegwfjnvwivmwrhriwcg"


def token_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        try:
            token = request.headers.get('Authorization')
            data = jwt.decode(token, SECRET_KEY)
            return f(*args, **kwargs)
        except:
            headers = {'Content-Type': 'application/json'}
            return jsonify({'message' : 'Token is invalid!'}), 401
            # Response(json.dumps({"message": "Unauthorized user"}), 401, headers=headers)
    return decorated()


@users.route('/user', methods=['GET'])
@token_required
def get_users():
    headers = {'Content-Type': 'application/json'}

    all_users = users_collection.find()
    result = []
    # When a user is returned the password must not be in the response body
    for user in all_users:
        result.append({'username': user['username'], 'email': user['email']})

    return Response(json.dumps({"Users": result}), status=200, headers=headers)
 

Комментарии:

1. Можете ли вы опубликовать полную трассировку стека сообщения об ошибке?

Ответ №1:

return decorated не return decorated() входит token_required . В противном случае вы будете вызывать обернутую функцию всякий раз, когда вы определяете оформленную функцию.

Комментарии:

1. Спасибо. Это было действительно просто, я думал, что это как-то связано со структурой моего проекта.