Создание настраиваемого разрешения при переносе данных

Я пытался создать пользовательское разрешение при миграции, однако после запуска миграции разрешение не было создано в таблице разрешений. Может ли кто-нибудь указать, в чем ошибка? Также я не уверен, что мне следует использовать в качестве связанной модели для ContentType, поскольку разрешение используется для ограничения пользователей, которые могут просматривать страницу, которая показывает сводку пользователей на сайте. Любая помощь будет принята с благодарностью, спасибо.

def add_view_aggregated_data_permissions(apps, schema_editor):
    ContentType = apps.get_model('django', 'ContentType')
    Permission = apps.get_model('auth', 'Permission')
    content_type = ContentType.objects.get(app_label='auth', model='user')
    permission = Permission.objects.create(codename='can_view_data',
                                           name='Can view data',
                                           content_type=content_type)

person Aithusa    schedule 23.07.2015    source источник
comment
Почему вы хотите создать разрешение таким образом?   -  person Wtower    schedule 23.07.2015
comment
Это неправильный способ сделать это? Я хочу создать разрешение для представления, как мне это сделать?   -  person Aithusa    schedule 23.07.2015


Ответы (3)


Я бы рекомендовал вам использовать стандартный способ использования настраиваемых разрешений, как описано в документация по Django. Вы вообще избежите многих проблем.

Чтобы создать настраиваемые разрешения для данного объекта модели, используйте метаатрибут модели разрешений.

В этом примере модели создается пользовательское разрешение:

class MyModel(models.Model):
    ...
    class Meta:
        permissions = (
            ('view_data', "Can see available data"),
        )

Единственное, что это делает, это создает эти дополнительные разрешения при запуске manage.py migrate. Ваш код отвечает за проверку значения этих разрешений, когда пользователь пытается получить доступ к функциям, предоставляемым приложением...

Затем вы можете использовать permission_required декоратор с вашим представлением, чтобы проверить наличие конкретного разрешения:

from django.contrib.auth.decorators import permission_required

@permission_required('myapp.view_data')
def my_view(request):
    ...
person Wtower    schedule 23.07.2015
comment
Означает ли это, что разрешение будет связано с моделью пользователя? Меня смутило то, что мое разрешение используется только для ограничения доступа к представлению, поэтому я не уверен, с какой моделью это связать. Кроме того, смогу ли я добавить это разрешение пользователям на сайте администратора? Изменить: только что понял, что не могу редактировать код в модели пользователя, так куда мне поместить метакод? Я новичок в этом, поэтому у меня может быть много вопросов... - person Aithusa; 23.07.2015
comment
Что вы имеете в виду, что разрешение будет связано с моделью пользователя? Все разрешения по существу связаны с моделью User. Если вам специально нужно добавить разрешение, например, для просмотра пользователей, то это совершенно другое дело, и вам нужно будет расширить или переопределить модель пользователя. Я предполагаю, что ваше представление будет отображать данные по крайней мере из какой-то модели, поэтому вы можете добавить разрешение на эту модель. - person Wtower; 23.07.2015
comment
Ах, хорошо, я думал, что ассоциация была чем-то вроде отношения разрешения к тому, какая модель сможет иметь это разрешение, но это не имеет особого смысла, я думаю, поэтому я запутался. Спасибо за разъяснение :) То есть, если представление содержит данные из разных моделей, мне нужно добавить разрешение только для одной модели? - person Aithusa; 23.07.2015
comment
Добро пожаловать. Это зависит от всего приложения, вы можете добавить разрешение только для одной модели или для всех моделей и проверить все разрешения (безопаснее). - person Wtower; 23.07.2015
comment
ПРИМЕЧАНИЕ: разрешение становится доступным только в конце команды migrate, поэтому, если у вас есть (т. е.) последующие миграции RunPython, которые ссылаются на новое разрешение, они не увидят новое разрешение, если оно применяется в той же команде migrate. В этом случае вам придется применять их в два этапа. - person sox with Monica; 11.06.2020

Я хотел создать собственное разрешение (чтение) для всех моделей приложений. Я сделал это два шага:

  1. Создайте расширенное разрешение из DjangoModelPermissions:

    class DjangoModelPermissionsExtended(DjangoModelPermissions):
        """
        """
        perms_map = {
            'GET': ['%(app_label)s.read_%(model_name)s'],
            'OPTIONS': [],
            'HEAD': [],
            'POST': ['%(app_label)s.add_%(model_name)s'],
            'PUT': ['%(app_label)s.change_%(model_name)s'],
            'PATCH': ['%(app_label)s.change_%(model_name)s'],
            'DELETE': ['%(app_label)s.delete_%(model_name)s'],
        }
    
  2. Поместите его в каждое представление, которое я хочу иметь разрешение на чтение:

    class ExampleViewSet(viewsets.ModelViewSet):
        permission_classes = (
            DjangoModelPermissionsExtended,
        )
    
  3. Создайте команду django customread .py:

    from django.core.management.base import BaseCommand, CommandError
    from project.app import models as app_models
    from django.db import models
    from django.contrib.auth.models import Permission
    from django.contrib.contenttypes.models import ContentType
    import inspect
    
    class Command(BaseCommand):
    help = 'Create the read permission to app models'
    
    def handle(self, *args, **options):
        for name, obj in inspect.getmembers(app_models):
            if inspect.isclass(obj) and issubclass(obj, models.Model):
                try:
                    self.add_canread(obj)
                    self.stdout.write(self.style.SUCCESS(
                        'created permission for %s' % obj
                    ))
                except Exception as e:
                    self.stdout.write(self.style.ERROR(
                        'Permission already exists for %s' % obj
                    ))
    
    def add_canread(self, object_class):
        """This a function that can be executed in order to create
        new permissions (read view) to a class in DB.
    
        """
        if inspect.isclass(object_class):
            content_type = ContentType.objects.get_for_model(object_class)
            permission = Permission.objects.create(
                codename='read_{}'.format(object_class._meta.model_name),
                name='Can view {}'.format(object_class.__name__),
                content_type=content_type,
            )
        else:
            msg = "The object is not a class"
            print(msg)
    
  4. Выполните его после выполнения миграции:

    python manage.py customread
    
person Shil Nevado    schedule 08.03.2018

Начиная с django 1.8 и встроенных миграций это очень безболезненно.

  1. Все, что вам нужно сделать, это добавить необходимые разрешения для соответствующей модели.
  2. Запустить makemigration

    ./manage.py сделать миграцию

  3. запустите миграцию, созданную на шаге выше

    ./manage.py перенести

person elewinso    schedule 18.01.2016