【问题标题】:Applying decorators to decorators将装饰器应用于装饰器
【发布时间】:2015-02-01 12:22:47
【问题描述】:

我为我的 Flask GAE 应用程序编写了两个装饰器:

def login_required(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if (not users.get_current_user()):
            return redirect(home_url)
        return f(*args, **kwargs)
    return decorated_function

def registration_required():
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if(not is_registered_user(users.get_current_user().user_id())):
            return redirect(user_reg_url)
        return f(*args, **kwargs)
    return decorated_function

对于应用程序中的大多数页面,用户都需要登录和注册,因此视图处理程序同时使用两个装饰器。例如,

@app.route(some_page)
@login_required
@registration_required
def some_page_view():
    # whatever code here

我认为从设计的角度来看,如果registration_required 的实现本身用login_required 装饰会更有意义,因为它需要用户登录才能检查他们是否已注册。我试过的是这样的:

@login_required
def registration_required():
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if(not is_registered_user(users.get_current_user().user_id())):
            return redirect(user_reg_url)
        return f(*args, **kwargs)
    return decorated_function

然后它可以单独用于视图处理程序,如下所示:

@app.route(some_page)
@registration_required
def some_page_view():
    # whatever code here

但是,当我尝试时,我收到错误 AttributeError: 'Response' object has no attribute '__name__'。在 Flask 中装饰装饰器时我需要做一些特别的事情吗?

【问题讨论】:

  • 你真的想装饰装饰器还是不想装饰装饰功能?当然,差异是相关的。
  • 请修正您发布的代码的缩进。
  • 问题是关于如何装饰装饰器。我很清楚您可以将多个装饰器应用于常规函数。
  • 我已经修复了缩进。当我从我的编辑器那里复制时,我没有意识到它被破坏了。
  • 现在我明白了你想要什么(通过第一个答案的帮助;-)。请提供您的代码。您只是说“当我尝试时”,但您没有指定用于“尝试”它的语法。

标签: python google-app-engine python-2.7 flask decorator


【解决方案1】:

执行此操作的最简单方法是简单地调用要包装在要返回的包装器上的装饰器:

def registration_required():
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if(not is_registered_user(users.get_current_user().user_id())):
            return redirect(user_reg_url)
        return f(*args, **kwargs)
    return login_required(decorated_function)

这是可行的,因为装饰器语法只是简写:

@decorator
def some_func():
    pass

等同于:

def some_func():
    pass

some_func = decorator(some_func)

还有:

@decorator2
@decorator1
def some_func():
    pass

等同于:

def some_func():
    pass

some_func = decorator2(decorator1(some_func))

【讨论】:

    猜你喜欢
    • 2020-11-30
    • 2011-05-06
    • 2011-10-05
    • 2011-09-03
    • 2015-11-18
    • 1970-01-01
    • 2020-01-11
    • 1970-01-01
    相关资源
    最近更新 更多