2009-11-16 14 views
68

estoy usando permisos personalizados en mis modelos de Django como esto:La adición de nuevos permisos personalizados en Django

class T21Turma(models.Model): 
    class Meta: 
     permissions = (("can_view_boletim", "Can view boletim"), 
         ("can_view_mensalidades", "Can view mensalidades"),) 

El problema es que cuando agrego un permiso de la lista que no consigue agrega a la tabla auth_permission cuando ejecuto syncdb. Qué estoy haciendo mal. Si hace alguna diferencia, estoy usando el sur para las migraciones de bases de datos.

+0

Usted puede fijar la longitud del campo en el modelo de permisos: http://stackoverflow.com/a/28343007/3310666 –

Respuesta

59

South no rastrea los permisos django.contrib.auth. Ver ticket #211 para más información.

Uno de los comentarios en el ticket sugiere que el uso de la opción --all en syncdb puede resolver el problema.

+1

Suena como exactamente mi problema, excepto que no puedo conseguir el interruptor --all para trabajar con syncdb ni encuentro el interruptor documentado en ningún lado. – user27478

+5

Esto funcionó después de que actualicé al sur 0.6.2 (estaba ejecutando 0.5) anteriormente. – user27478

+0

Esto me da el error "DatabaseError: value too long for type character (50)" – Cerin

48

Si desea que "manage.py migrate" haga todo (sin llamar a syncdb --all). Es necesario crear nuevos permisos con una migración:

[email protected]> manage.py datamigration myapp add_perm_foo --freeze=contenttypes --freeze=auth 

Editar el archivo creado:

class Migration(DataMigration): 

    def forwards(self, orm): 
     "Write your forwards methods here." 
     ct, created = orm['contenttypes.ContentType'].objects.get_or_create(
      model='mymodel', app_label='myapp') # model must be lowercase! 
     perm, created = orm['auth.permission'].objects.get_or_create(
      content_type=ct, codename='mymodel_foo', defaults=dict(name=u'Verbose Name')) 
+1

gracias, este enfoque parece más consistente –

+2

no hay necesidad de las últimas tres líneas, el argumento de palabra clave 'defaults' de' get_or_create' se puede usar en su lugar [link] (https://docs.djangoproject.com/en/dev/ ref/models/querysets/# django.db.models.query.QuerySet.get_or_create) –

+5

Si está utilizando este método, debe agregar las opciones '--freeze = contenttypes --freeze = auth' al comando datamigration. De lo contrario, obtendrá el error @balmaster menciona a continuación. E.g: 'manage.py datamigration myapp add_perm_foo --freeze = contenttypes --freeze = auth' – calebbrown

2

Cuando i runnning la migración con el siguiente código

ct, created = orm['contenttypes.ContentType'].objects.get_or_create(model='mymodel',  app_label='myapp') # model must bei lowercase! 
perm, created = orm['auth.permission'].objects.get_or_create(content_type=ct, codename='mymodel_foo') 

que conseguir folloving error

File "C:\Python26\lib\site-packages\south-0.7.3-py2.6.egg\south\orm.py", line 170, in __getitem__ 
raise KeyError("The model '%s' from the app '%s' is not available in this migration." % (model, app)) 
KeyError: "The model 'contenttype' from the app 'contenttypes' is not available in this migration." 

Para evitar este error, he modificado el código

from django.contrib.contenttypes.models import ContentType 
from django.contrib.auth.models import Permission 

class Migration(DataMigration): 

    def forwards(self, orm): 
     "Write your forwards methods here." 
     ct = ContentType.objects.get(model='mymodel', app_label='myapp') 
     perm, created = Permission.objects.get_or_create(content_type=ct, codename='mymodel_foo') 
     if created: 
      perm.name=u'my permission description' 
      perm.save() 
+7

Mala idea; deberías usar el ORM congelado.Agregue '--freeze = contenttypes --freeze = auth' a su línea de comando' ./manage.py datamigration'. –

20

Puede conectarse a la señal post_migrate con el fin de actualizar los permisos después de la migración. Utilizo el siguiente código, ligeramente modificado desde Dev with Passion y originalmente desde django-extensions.

# Add to your project-level __init__.py 

from south.signals import post_migrate 

def update_permissions_after_migration(app,**kwargs): 
    """ 
    Update app permission just after every migration. 
    This is based on app django_extensions update_permissions management command. 
    """ 
    from django.conf import settings 
    from django.db.models import get_app, get_models 
    from django.contrib.auth.management import create_permissions 

    create_permissions(get_app(app), get_models(), 2 if settings.DEBUG else 0) 

post_migrate.connect(update_permissions_after_migration) 
+0

¡Esta es la mejor manera de resolver este problema! – joctee

+1

Esto tiene un problema cuando se trabaja con algo así como gunicorn para ejecutar la aplicación, es decir, falla al encontrar la variable de entorno que se establece en el archivo wsgi.py. –

27

Esto funcionó para mí:

./manage.py update_permissions 

es una cosa django-extensions.

+1

"DatabaseError: value too long for type character variation (50)". La causa es que mi nombre de permiso fue demasiado largo, pero ese es un mensaje de error terriblemente inútil, especialmente cuando agrego docenas de nuevos permisos. – Cerin

Cuestiones relacionadas