使用具有属性的自定义属性来装饰方法

时间:2013-04-17 15:49:32

标签: python django attributes decorator python-decorators

我有一些具有属性的方法(使用.Net术语)。像。的东西。

#Example Usage
@RequireLoggedIn
def SomeAuthorisedFunction():
    # ...

该属性定义为

def RequireLoggedIn(func):
    func.AuthenticationRequired = True
    return func

然后,我可以使用hasattr(view_func, 'AuthenticationRequired')检查是否已设置此项。我想做的就是这样......

@RequireRole('Administrator')
def SomeAuthorisedFunction():
    # ...

我尝试过定义这样的属性:

def RequireRole(func, Role):
    func.RequiresRole = Role
    return func

@RequireRole('Administrator')会导致missing positional argument "Role"@RequireRole(Role='Administrator')结果为missing positional argument "func"

如何指定属性的属性?

2 个答案:

答案 0 :(得分:3)

您需要创建一个嵌套函数; RequireRole函数应返回实际的装饰器函数:

def RequireRole(Role):
    def decorator(func):
        func.RequiresRole = Role
        return func
    return decorator

@expression语法只不过是语法糖,以下设置:

@decorator
def foo(): pass

被翻译为:

def foo(): pass
foo = decorator(foo)

代替。但decorator部分本身也可以是表达式;这就是你尝试使用它的方式。因此,当您使用@RequireRole('Administrator')作为装饰器时,您真的会这样做:

def SomeAuthorisedFunction():
    # ...
SomeAuthorisedFunction = RequireRole('Administrator')(SomeAuthorisedFunction)

注意那里的 double 函数调用!这就是我的RequireRole()版本返回嵌套函数的原因。这是你申请时会发生的事情:

  1. def SomeAuthorizedFunction(): functionbody已执行。
  2. RequireRole('Administrator') is executed. It returns a scoped decorator()`function。
  3. 调用此返回的函数并在步骤1的SomeAuthorizedFunction函数中传递。
  4. 作用域decorator()函数将.RequiresRole属性添加到函数中,并在步骤2中将作用域Role传递给RequireRole。函数将返回。
  5. Python将步骤4的返回值分配给名称SomeAuthorizedFunction

答案 1 :(得分:1)

您的RequireRole函数必须返回装饰器函数。这很容易 通过嵌套函数完成,如下所示:

>>> def RequireRole(role):
...   def RequireRole(func):
...     func.RequiresRole = role
...     return func
...   return RequireRole
... 
>>> @RequireRole('Administrator')
... def SomeAuthorisedFunction():
...   pass
... 
>>> print SomeAuthorisedFunction.RequiresRole
Administrator
>>>