【问题标题】:Flask - 'NoneType' object is not callableFlask - 'NoneType' 对象不可调用
【发布时间】:2012-08-10 00:14:44
【问题描述】:

我正在开发我的第一个 Flask 应用程序。直接从this 中提取一些代码,我试图确保用户的cookie 中存在一个值。

def after_this_request(f):
    if not hasattr(g, 'after_request_callbacks'):
        g.after_request_callbacks = []
    g.after_request_callbacks.append(f)
    return f

@app.after_request
def call_after_request_callbacks(response):
    for callback in getattr(g, 'after_request_callbacks', ()):
        response = callback(response)
    return response

@app.before_request
def detect_unique_id():
    unique_id = request.cookies.get('unique_id')
    if unique_id is None:
        unique_id = generate_unique_id()
        @after_this_request
        def remember_unique_id(response):
            response.set_cookie('unique_id', unique_id)
    g.unique_id = unique_id

我不断收到此错误:

Traceback (most recent call last):
  File "/..../env/lib/python2.7/site-packages/flask/app.py", line 1701, in __call__
    return self.wsgi_app(environ, start_response)
  File "/..../env/lib/python2.7/site-packages/flask/app.py", line 1690, in wsgi_app
    return response(environ, start_response)
TypeError: 'NoneType' object is not callable

我正在尝试了解此错误的原因。请帮忙。

【问题讨论】:

  • 当我忘记返回渲染的模板时遇到了同样的错误,而是在 Flask View 子类的 dispatch_request 方法中返回 None

标签: python flask werkzeug


【解决方案1】:

问题

remember_unique_id 不返回响应对象,但call_after_request_callbacks 将调用每个通过after_this_request 装饰器添加的回调的结果分配给result,然后返回。也就是说:

# This
for callback in getattr(g, 'after_request_callbacks', ()):
    response = callback(response)

# translates to this
for callback in [remember_unique_id]:
    response = callback(response)

# which translates to this
response = remember_unique_id(response)

# which translates to this
response = None

解决方案

要么:

  • 更新remember_unique_id 以返回修改后的响应对象
  • 更新call_after_request_callbacks 以检查返回的对象并确保它不是None:

    for callback in getattr(g, 'after_request_callbacks', ()):
        result = callback(response)
        if result is not None:
            response = result
    

为什么会这样?

Flask 是一个 WSGI 应用程序,它期望 response 是一个 WSGI 应用程序(即可调用对象)。当它处理来自视图模板的响应时,它会运行一些检查以确保它可以用作响应对象,如果返回的值不是 WSGI 应用程序,它会将其转换为一个。它确实检查响应对象是否未被after_request 装饰器更改,因此当它尝试调用响应对象时(此时它假定它是一个有效的 WSGI 应用程序)你会得到TypeError

【讨论】:

  • 谢谢!这完全回答了我的问题。
猜你喜欢
  • 1970-01-01
  • 2019-11-29
  • 2021-02-14
  • 2015-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-17
相关资源
最近更新 更多