Flask: before_request 检查会话和/或 Cookie 不生效

1 投票
1 回答
3340 浏览
提问于 2025-04-18 09:58

这是我的代码:

blueprint = Blueprint('client', __name__, template_folder='templates')

@blueprint.before_request
def load_session_from_cookie():
    account = check_sso_cookie(request.cookies, for_view=False)

    # if error occurred, return error
    if 'message' in account:
        session.pop('accountId', None)
        return redirect(settings.LOGIN_URL)

    if 'accountId' in session:
        return redirect(url_for('home'))
    elif 'accountId' in account:
        session['accountId'] = account.get('accountId')
        return redirect(url_for('home'))
    else:
        session.pop('accountId', None)
        return redirect(settings.LOGIN_URL)

请原谅我的无知,这是我第一个使用Flask的应用程序,涉及到会话管理。上面的代码总是返回一个错误,错误信息是RuntimeError: working outside of request context

以下是错误的详细信息:

Traceback (most recent call last):
  File "runserver.py", line 1, in <module>
    from api import app
  File "/Users/dmonsewicz/dev/autoresponders/api/__init__.py", line 13, in <module>
    import client
  File "/Users/dmonsewicz/dev/autoresponders/api/client/__init__.py", line 33, in <module>
    @blueprint.before_request(load_session_from_cookie())
  File "/Users/dmonsewicz/dev/autoresponders/api/client/__init__.py", line 16, in load_session_from_cookie
    account = check_sso_cookie(request.cookies, for_view=False)
  File "/Users/dmonsewicz/.virtualenvs/autoresponders-api/lib/python2.7/site-packages/werkzeug/local.py", line 338, in __getattr__
    return getattr(self._get_current_object(), name)
  File "/Users/dmonsewicz/.virtualenvs/autoresponders-api/lib/python2.7/site-packages/werkzeug/local.py", line 297, in _get_current_object
    return self.__local()
  File "/Users/dmonsewicz/.virtualenvs/autoresponders-api/lib/python2.7/site-packages/flask/globals.py", line 20, in _lookup_req_object
    raise RuntimeError('working outside of request context')

有没有其他人遇到过这个问题?

1 个回答

3

你需要注册的是函数本身,而不是函数的返回值:

blueprint.before_request(load_session_from_cookie)

注意,这里也不要加@。这样做是把函数对象传给blueprint.before_request()这个注册方法。

而你那种写法是先调用了load_session_from_cookie这个函数,但在你的模块加载时,还没有请求,所以就出现了异常。

@装饰器的写法通常是在函数定义之前,Python会自动帮你调用它:

@blueprint.before_request
def load_session_from_cookie():
    # ... your function ...

注意这次我们没有直接调用它。

后面的写法是推荐的语法,只有在你不能在模块加载时使用装饰器的情况下(比如blueprint是动态加载的,或者在一个蓝图工厂函数中等),才需要用到前面的那种写法。

撰写回答