【问题标题】:Flask - custom decorator breaks the routingFlask - 自定义装饰器破坏路由
【发布时间】:2012-06-19 07:49:09
【问题描述】:

我有以下 Flask 路由和自定义助手:

from spots import app, db
from flask import Response
import simplejson as json


def json_response(action_func):
    def create_json_response(*args, **kwargs):
        ret = action_func(*args, **kwargs)
        code = 200
        if len(ret) == 2:
            code = ret[0]
            resp = ret[1]
        else:
            resp = ret[0]
        return Response(
            response=json.dumps(resp, indent=4),
            status=code,
            content_type='application/json'
        )

    return create_json_response


@app.route('/test')
@json_response
def test():
    return 400, dict(result="Test success")


@app.route('/')
@json_response
def home():
    return 200, dict(result="Home success")

我希望 /test 的 GET 请求返回类似 {"result":"Test success"} 的内容,但事实并非如此。相反,任何请求似乎都匹配最后一条路由,即home。为什么?

我想知道这是否是由于对 json_response 的不同调用之间缺乏绝缘造成的?

提前致谢。

【问题讨论】:

  • code = ret[0]; resp = ret[1] 会像 code, resp = ret 一样整洁,resp = ret[0] 会像 resp, = ret 一样整洁(尽管我认为这仍然不是您想要使用它的方式,您的函数需要 @987654331 @ 而不是 return {})。除此之外,我觉得它是正确的。
  • 只是猜测 - 函数的签名已损坏,您可能想尝试functools.wraps
  • 我想看看这个问题的答案
  • @VidulPetrov 您的解决方案有效 - 使用 functools.wraps 解决了问题。
  • 请注意 - Flask 提供了一个 jsonify 函数,该函数将执行您的自定义装饰器所做的事情,但在 return 语句中(您只需将 dict 替换为 jsonify)。

标签: python json decorator flask


【解决方案1】:

正如Видул Петров 所说,解决方案是使用functools.wraps

import functools
def json_response(action_func):
    @functools.wraps(action_func)
    def create_json_response(*args, **kwargs):
        ...
return create_json_response

原因是 Flask 的路由系统将 URL 映射到“端点”,然后将端点映射到视图函数。端点默认为视图函数的__name__ 属性。在这种情况下,装饰函数被传递给app.route,因此两个规则的端点都是create_json_response,并且在两种情况下都使用了为该端点定义的最后一个视图。

functools.wraps 从原始函数中获取__name__(和其他属性)并修复此问题。在装饰包装中使用它总是一个好主意。

【讨论】:

猜你喜欢
  • 2018-06-05
  • 2020-05-19
  • 2020-11-21
  • 1970-01-01
  • 2019-03-29
  • 2021-11-27
  • 1970-01-01
  • 1970-01-01
  • 2015-05-17
相关资源
最近更新 更多