flask路由装饰器RuntimeError

时间:2015-12-07 09:43:39

标签: python python-2.7 flask decorator python-decorators

我写了一个简单的烧瓶app,它为用户返回指定的id。我想让每个路由使用相同的逻辑,所以我想将它作为装饰器来实现。

# the decorator
def session_decorator(data_handle_func):
     session_id = request.cookies.get('static')
    if session_id is None:
        session_id = uuid.uuid1().hex
    resp = make_response(data_handle_func(session_id))
    resp.set_cookie('static', session_id)
    return resp

# version 1
@app.route("/session")
def sessionx():
    def simple(session_id):
         return session_id
    return session_decorator(simple)

# version 2, throw excetion 
@app.route("/session2")
@session_decorator
def sessionx(session_id):
    return session_id

第一个版本运行正常。第二个是所需的版本,抛出:

Traceback (most recent call last):
  File "app.py", line 466, in <module>
    @session_decorator
  File "app.py", line 451, in session_decorator
    session_id = request.cookies.get('static')
  File "/home/users/install/python/lib/python2.7/site-packages/Werkzeug-0.11-py2.7.egg/werkzeug/local.py", line 342, in __getattr__
    return getattr(self._get_current_object(), name)
  File "/home/users/install/python/lib/python2.7/site-packages/Werkzeug-0.11-py2.7.egg/werkzeug/local.py", line 301, in _get_current_object
    return self.__local()
  File "/home/users/install/python/lib/python2.7/site-packages/Flask-0.10.1-py2.7.egg/flask/globals.py", line 20, in _lookup_req_object
    raise RuntimeError('working outside of request context')
RuntimeError: working outside of request context

更新

根据这个related question,我编写了以下装饰器,它起作用。但我不知道为什么会这样,以及实际上导致RuntimeError的原因是什么?有人可以对此提出一些建议吗?

def session_decorator_v2(data_handle_func):
    @functools.wraps(data_handle_func)
    def decorated_function(*args, **kws):
        session_id = request.cookies.get('static')
        if session_id is None:
            print "not exist"
            session_id = uuid.uuid1().hex
        resp = make_response(data_handle_func(session_id))
        resp.set_cookie('static', session_id)
        return resp
    return decorated_function

1 个答案:

答案 0 :(得分:1)

你的装饰者被错误地定义了。它必须是一个函数,返回一个将被执行的函数并调用data_handle_func

# the decorator
def session_decorator(data_handle_func):
    def session_parser():
        session_id = request.cookies.get('static')
        if session_id is None:
            session_id = uuid.uuid1().hex
        resp = make_response(data_handle_func(session_id))
        resp.set_cookie('static', session_id)
        return resp
    return session_parser

# version 2, throw excetion 
@app.route("/session2")
@session_decorator
def sessionx(session_id):
    return session_id

您看到此错误的原因是因为您的“装饰器”会在连接到路径后立即执行。当你做request.cookies.get('static')时,Flask正在哭,因为它还没有请求上下文(你正在初始化应用程序,而不是处理请求)

编辑OP的更新: 您提供的代码与我提供的代码完全相同。

@functools.wraps(data_handle_func)

是一个装饰器,它将函数名称和描述放入包装函数中。因此装饰器在使用时不会更改丢失描述的名称。

装饰器基本上只是一个函数,当应用于函数时将返回一个函数...