我正在尝试使用模型继承为我的所有Django模型添加动态Meta属性,但我无法使其工作。我有一个权限,我想添加到我的所有模型中:
class ModelA(models.Model):
class Meta:
permisssions =(('view_modela','Can view Model A'),)
class ModelB(models.Model):
class Meta:
permisssions =(('view_modelb','Can view Model B'),)
我尝试创建一个这样的抽象基类:
class CustomModel(models.Model):
def __init__(self, *args, **kwargs):
self._meta.permissions.append(('view_'+self._meta.module_name, u'Can view %s' % self._meta.verbose_name))
super(CustomModel,self).__init__(*args, **kwargs)
class ModelA(CustomModel):
....
class ModelB(CustomModel):
...
但它不起作用。这是正确的方法吗?因为Django使用内省来构造Model类,所以我不确定在类的__init__()
期间添加权限是否会起作用。使用我当前的实现,每次访问模型实例时,它都会附加另一个权限元组。
答案 0 :(得分:24)
你的直觉是对的,这是行不通的。在Django中,权限存储在数据库中,这意味着:
_meta.permissions
中的__init__
,User
对象也不会在任何权限检查调用中将其选中,因为这些会查询数据库中的权限表(和那个表的缓存,在那)。这里你真正需要的是一个元类...你的目标无法通过继承来实现。元类在定义之前动态地重写ModelA
和ModelB
类定义,因此它不需要ModelA
实例,并且可用于syncdb。由于Django的模型也首先使用元类来构建Meta
对象,唯一的要求是你的元类必须继承与Django模型相同的元类。这是一些示例代码:
from django.db.models.base import ModelBase
class CustomModelMetaClass(ModelBase):
def __new__(cls, name, bases, attrs):
klas = super(CustomModelMetaClass, cls).__new__(cls, name, bases, attrs)
klas._meta.permissions.append(('view_' + klas._meta.module_name, u'Can view %s' % klas._meta.verbose_name))
return klas
class ModelA(models.Model):
__metaclass__ = CustomModelMetaClass
test = models.CharField(max_length=5)
请注意,此情况下的权限仅在syncdb
上写入。如果您需要在运行时根据用户动态更改权限,则需要提供自己的authentication backend。
答案 1 :(得分:0)
尝试使用自定义管理器:
#create a custom manager
class DynTableNameManager(models.Manager):
#overwrite all() (example)
#provide table_name
def all(self, table_name):
from django.db import connection
cursor = connection.cursor()
cursor.execute("""
SELECT id, name
FROM %s
""" % table_name)
result_list = []
for row in cursor.fetchall():
p = self.model(id=row[0], name=row[1])
result_list.append(p)
return result_list
#cerate a dummy table
class DummyTable(models.Model):
name = models.CharField ( max_length = 200 )
objects = DynTableNameManager()
像这样使用:
f = DummyTable.objects.all('my_table_name')