将装饰器应用于装饰器

时间:2014-12-03 19:37:30

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

我为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中装饰装饰器有什么特别之处吗?

1 个答案:

答案 0 :(得分: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))