Добавление новых пользовательских разрешений в Django

Я использую настраиваемые разрешения в своих моделях Django следующим образом:

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

Проблема в том, что когда я добавляю разрешение в список, оно не добавляется в таблицу auth_permission при запуске syncdb. Что я делаю неправильно. Если это имеет значение, я использую юг для миграции базы данных.


person gerdemb    schedule 16.11.2009    source источник
comment
Вы можете исправить длину поля в модели разрешений: stackoverflow.com/a/28343007/3310666   -  person Missing Semicolon    schedule 05.02.2015


Ответы (5)


South не отслеживает разрешения django.contrib.auth. Для получения дополнительной информации см. билет № 211.

Один из комментариев к заявке предполагает, что использование параметра --all в syncdb может решить проблему.

person Daniel Naab    schedule 16.11.2009
comment
Похоже на мою проблему, за исключением того, что я не могу заставить переключатель --all работать с syncdb и нигде не нахожу этот переключатель задокументированным. - person gerdemb; 16.11.2009
comment
Это сработало после того, как я обновился до южной версии 0.6.2 (у меня была версия 0.5). - person gerdemb; 18.11.2009
comment
Это просто дает мне ошибку DatabaseError: слишком длинное значение для переменного символа типа (50) - person Cerin; 15.08.2013
comment
это означает, что у вас уже есть значение в БД, длина которого превышает 50 символов. - person caesarsol; 23.10.2013
comment
@Cerin - я понял это, когда описание моего разрешения было более 50 символов. Кажется вероятным местом, чтобы сделать эту ошибку. - person Rob Grant; 18.08.2014

Если вы хотите, чтобы «manage.py migrate» делал все (без вызова syncdb --all). Вам необходимо создать новые разрешения с миграцией:

user@host> manage.py datamigration myapp add_perm_foo --freeze=contenttypes --freeze=auth

Отредактируйте созданный файл:

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'))
person guettli    schedule 27.05.2011
comment
нет необходимости в последних трех строках, вместо них можно использовать defaults аргумент ключевого слова get_or_create ссылка - person Ivan Virabyan; 02.08.2011
comment
Если вы используете этот метод, вам нужно добавить параметры --freeze=contenttypes --freeze=auth в команду переноса данных. В противном случае вы получите сообщение об ошибке, упомянутое @balmaster ниже. Например: manage.py datamigration myapp add_perm_foo --freeze=contenttypes --freeze=auth - person calebbrown; 20.12.2011

Это сработало для меня:

./manage.py update_permissions

Это django-extensions.

person wouldnt    schedule 30.04.2013
comment
Ошибка базы данных: слишком длинное значение для изменяющегося символа типа (50). Причина в том, что имя моего разрешения было слишком длинным, но это ужасно бесполезное сообщение об ошибке, особенно когда я добавляю десятки новых разрешений. - person Cerin; 15.08.2013

Вы можете подключиться к сигналу post_migrate, чтобы обновить разрешения после миграции. Я использую следующий код, слегка измененный из Dev with Passion и первоначально из 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)
person Vebjorn Ljosa    schedule 11.08.2012
comment
У этого есть проблема при работе с чем-то вроде gunicorn для запуска приложения, а именно: ему не удается найти переменную среды, установленную в файле wsgi.py. - person Pier1 Sys; 31.07.2013

Когда я запускаю миграцию со следующим кодом

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

Я получаю следующую ошибку

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."

Чтобы предотвратить эту ошибку, я изменил код

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()
person balmaster    schedule 04.08.2011
comment
Плохая идея; вы должны использовать замороженный ORM. Добавьте --freeze=contenttypes --freeze=auth в командную строку ./manage.py datamigration. - person Vebjorn Ljosa; 20.07.2012