代码之家  ›  专栏  ›  技术社区  ›  gerdemb

Django模型的动态元属性?

  •  10
  • gerdemb  · 技术社区  · 17 年前

    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__()

    2 回复  |  直到 17 年前
        1
  •  26
  •   bignose    6 年前

    • 当运行syncdb时,它们需要在类级别可用,以便填充authpermission表(并且您的方法需要一个实例,在syncdb期间不会创建)
    • _meta.permissions 在 __init__ ,the User

    你的目标无法通过继承来实现。你真正需要的是 Python metaclass .

    ModelA 和 ModelB Meta

    以下是一些示例代码(Python 2):

    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_{0.module_name}'.format(klas._meta),
                    u'Can view {0.verbose_name}'.format(klas._meta))
            )
    
            return klas
    
    class ModelA(models.Model):
    
        __metaclass__ = CustomModelMetaClass
    
        test = models.CharField(max_length=5)
    

    Python 3:

    from django.db.models.base import ModelBase
    
    class CustomModelMetaClass(ModelBase):
    
        def __new__(cls, name, bases, attrs):
            klas = super().__new__(cls, name, bases, attrs)
            klas._meta.permissions.append(
                (
                    'view_{0.module_name}'.format(klas._meta),
                    'Can view {0.verbose_name}'.format(klas._meta))
            )
    
            return klas
    
    class ModelA(models.Model, metaclass=CustomModelMetaClass):
    
        test = models.CharField(max_length=5)
    

    请注意,在这种情况下,权限将仅写入 migrate 。如果需要在运行时根据用户动态更改权限,则需要提供自己的权限 authentication backend .

        2
  •  1
  •   rexus    16 年前

    #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')