关于Python(Pylons)中授权和重定向装饰器的帮助

1 投票
1 回答
2584 浏览
提问于 2025-04-15 22:05

我正在尝试写一个简单的装饰器,用来检查用户是否登录,如果没有登录,就把他引导到登录页面:

def authenticate(f):
    try:
        if user['authenticated'] is True:
            return f
    except:
        redirect_to(controller='login', action='index')

class IndexController(BaseController):
    @authenticate
    def index(self):
        return render('/index.mako' )

但是这个方法不管用。当用户已经登录时,一切正常。但如果用户没有登录,redirect_to() 就不工作了,我收到了这个错误:

HTTPFound: 302 Found Content-Type: text/html; charset=UTF-8 Content-Length: 0 location: /login

谢谢你的帮助!

1 个回答

5

我对Pylons不太了解,但看起来你写的装饰器有些问题。

装饰器是一个可以被调用的东西,它必须返回一个可以被调用的东西。装饰器在函数定义的时候就会被调用,它应该返回一个可以被调用的东西(通常是一个函数),这个返回的东西会替代被装饰的函数。

在你的例子中,装饰器只有在用户认证通过的情况下,才会返回一个可以调用的东西,这个认证是在index()函数定义的时候进行的。

你可以试着这样重写:

def authenticate(func):
    def call(*args, **kwargs):
        if user['authenticated'] is True:
            return func(*args,**kwargs)
        else:
            return redirect_to(controller='login', action='index')
    return call

在这里,authenticate()定义了一个内部函数,这个内部函数会替代被装饰的函数。现在,当你使用这个装饰器装饰一个函数时:

@authenticate
def index(self):
    return render('/index.mako' )

这意味着每次你调用index()时,实际上是在调用你装饰器中定义的内部函数。

你应该注意:由于Python中函数的定义方式,装饰器返回的函数对象仍然记得它被定义时的参数值。call()仍然知道在调用装饰器时传入的参数func。(这被称为闭包)

虽然装饰器不复杂,但理解起来确实有点难。你可以在谷歌上搜索关于装饰器的教程,有很多资源可以帮助你更清楚地理解这个概念,远比Python的文档要清晰得多。

撰写回答