13

私は最初のFlaskアプリケーションに取り組んでいます。これから直接いくつかのコードを取り出してユーザーの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

このエラーの理由を理解しようとしています。助けてください。

4

1 に答える 1

13

問題

remember_unique_idは応答オブジェクトを返しませんが、デコレータをcall_after_request_callbacks介して追加された各コールバックを呼び出した結果をに割り当ててから返します。つまり、次のようになります。after_this_requestresult

# 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アプリケーションでない場合は1つに変換します。応答オブジェクトがデコレータによって変更されていないafter_requestかどうかはチェックされないため、応答オブジェクト(この時点で有効なWSGIアプリケーションであると想定)を呼び出そうとすると、が取得されますTypeError

于 2012-08-13T18:54:04.937 に答える