在我们使用Django进行开发的应用程序中,在某些情况下,我们需要为拥有所有者的某些模型自动为用户分配权限(字段名称没有规则,可以是“用户”,“所有者” ,“教练”等,也可以有多个字段。)我的解决方案是创建一个包含那些字段名称的装饰器,它将放在模型定义之前,如下所示(不使用样本中特定于django的代码):
@auto_assign_perms('owner', 'user')
class Test(Base):
pass
假设Base
是在Django的Model
类之后派生的抽象类,我在其中添加了在保存对象后分配权限的功能。现在我只打印分配给该类的用户列表。您可以在下面找到装饰器和Base
类的代码:
class auto_assign_perms(object):
def __init__(self, *users):
self.users = users
def __call__(self, cls):
cls.owners.update(self.users)
return cls
class Base(object):
owners = set()
def save(self, *args, **kwargs):
for owner in self.owners:
print owner,
print
我的模型看起来像这样:
@auto_assign_perms('owner', 'user')
class Test(Base):
pass
@auto_assign_perms('coach')
class Test2(Base):
pass
问题是两个子类都包含所有三个字段('owner', 'user', 'coach')
,print self.__class__.__name__
方法中的Base.save()
正确显示“Test”或“Test2”。我尝试在get_owners()
类中添加classmethod Base
然后迭代其结果,但它没有帮助。
我怎么解决这个问题?也许我应该使用元类(我还没有得到它们)?提前谢谢。
答案 0 :(得分:4)
您需要设置所有者列表,而不是更新:
class auto_assign_perms(object):
def __init__(self, *users):
self.users = users
def __call__(self, cls):
cls.owners = set(self.users) # <- here
return cls
#some tests
@auto_assign_perms('owner', 'user')
class Test(Base):
pass
@auto_assign_perms('coach')
class Test2(Base):
pass
t = Test()
t.save()
t = Test2()
t.save()
>>>
owner user
coach
答案 1 :(得分:1)
您使用owners
作为Base
的类变量,因此每当您更改owners
时,所有派生类都会看到更改。
要解决此问题,您应该将owners
变量定义为派生类的类变量:
class Base(object):
def save(self, *args, **kwargs):
for owner in self.owners:
print owner,
print
@auto_assign_perms('owner', 'user')
class Test(Base):
owners = set()
@auto_assign_perms('coach')
class Test2(Base):
owners = set()
答案 2 :(得分:0)
叫我偏执,但我发现这个解决方案更优雅,因为我认为你根本不需要所有者成为一个类变量:
def auto_assign_perms(*users):
def class_wrapper(cls):
class ClassWrapper(cls):
def __init__(self, owners=users):
super(cls, self).__init__(owners=owners)
ClassWrapper.__name__ = cls.__name__
ClassWrapper.__module__ = cls.__module__
return ClassWrapper
return class_wrapper
class Base(object):
def __init__(self, owners=None):
if owners is None:
owners = set()
self.owners = owners
def save(self, *args, **kwargs):
for owner in self.owners:
print owner,
print
@auto_assign_perms('owner', 'user')
class Test1(Base):
pass
@auto_assign_perms('coach')
class Test2(Base):
pass
class Test3(Base):
pass
t = Test1(); t.save() # owner user
t = Test2(); t.save() # coach
t = Test3(); t.save() #