atributos dinâmicos Meta para Django Models?

votos
8

Eu estou tentando adicionar um atributo Meta dinâmico para todos os meus modelos do Django usando herança modelo, mas não posso fazê-lo funcionar. Eu tenho uma permissão que eu quero adicionar a todos os meus modelos como este:

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

Eu tentei criar uma classe base abstrata como este:

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):
    ...

mas ele não está funcionando. É este o caminho certo? Porque Django usa introspecção para construir as classes de modelo, eu não tenho certeza se a adição de permissões durante o __init__()da classe vai mesmo trabalhar. Com a minha implementação atual cada vez que acessar uma instância de modelo ele acrescenta uma outra tupla das permissões.

Publicado 07/04/2009 em 15:07
fonte usuário
Em outras línguas...                            


2 respostas

votos
23

Seu instinto está certo de que isso não vai funcionar. Em Django, permissões são armazenadas no banco de dados, o que significa que:

  • eles precisam estar disponíveis ao nível de classe quando syncdb é executado, a fim de preencher a tabela de auth_permission (e sua abordagem requer uma instância, o que não será feita durante syncdb)
  • Mesmo se você não adicioná-lo a _meta.permissionsno __init__, o Userobjeto não iria buscá-lo em todas as chamadas de seleção de permissão porque aqueles consulte a tabela de permissões no DB (e um cache de tabela, em que).

O que você realmente precisa aqui é um metaclass ... seu objetivo não pode ser realizada utilizando herança. O metaclass re-escreve seus ModelAe ModelBclasse definições dinamicamente antes de serem definidas, portanto, não necessita de um ModelAexemplo, e está disponível para syncdb. Como os modelos do Django também utilizar metaclasses para construir o Metaobjeto, em primeiro lugar, a única exigência é que seus metaclass deve herdar a mesma metaclass como modelos do Django. Aqui está um código de exemplo:

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)

Observe que as permissões neste caso será escrito apenas em syncdb. Se você precisar alterar as permissões dinamicamente na base tempo de execução no usuário, você vai querer fornecer seu próprio backend de autenticação .

Respondeu 08/04/2009 em 00:15
fonte usuário

votos
0

Tente usar um gerenciador de costume:

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

use assim:

f = DummyTable.objects.all('my_table_name')
Respondeu 25/02/2010 em 13:40
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more