Skip to content

Role Dynamic Link

Читая эту документация возможно у вас появился вопрос:

Если все роли динамические, то как мы на backend сможем гарантированно получить, допустим, всех менеджеров?

Или

Как мне реализовать функционал, когда одна роль имеет полномочия над другой ролью, например менеджер должен иметь возможность изменять проценты у дилера? Ответ на который следующий: необходимо сделать статическое связывание ролей.

Что оно из себя представляет:

Статическое связывание обеспечивает модель RoleDynamicLink:

class RoleDynamicLink(models.Model):  
    # TODO write ADT settings module  
    roles = settings.ADVANTAGE.get('DYNAMIC_ROLES').get('DYNAMIC_LINK').get('ROLES')  # описывает все роли системы
    objects = RoleDynamicLinkManager() # менеджер объектов (подробности ниже)

    name = models.CharField(max_length=100) # отображаемое имя
    codename = models.CharField(max_length=50) # необходимо для получения всех пользователей данной роли в коде.  
    groups = models.ManyToManyField(Group) # группы пользователей (если пользователь состоит хотя бы в одной из указанных групп - система считает, что пользователь имеет данную роль)

Она представляет из себя модель, которая сообщает, что пользователи, состоящие в группах groups являются codename.

ВАЖНО! Если вы создаёте несколько для роли, то может возникнуть ситуация, когда пользователи, фактически не владеющие правами доступа определённой роли, будут числится, как владеющие данной ролью. Прошу быть внимательным при настройке.

Пример использования DynamicLink:

Допустим у нас в системе есть определённые роли:

roles = {  
    'admin': "Админестратор",  
    'manager': "Менеджер",  
    'subdistributor': "Субдистрибьютор",  
    'dealer': "Дилер",  
}

При инициализации проекта они автоматически создадутся в базе данных, если не были созданы ранее (проверка существования производится по codename)

В админ панели django вы можете произвести привязку django group к каждой записи в DynamicLink.

Чтобы получить QuerySet людей, обладающих ролью admin необходимо обратиться к специальному методу в object manager модели DynamicLink:

magaers_users_qs = RoleDynamicLink.objects.get_users_by_role('manager')

ВАЖНО! На данный момент специфика работы такова, что QuerySet запекается. Это означает, что полученный QuerySet после выполнения метода get_users_by_role, будет актуален ТОЛЬКО на момент выполнения метода get_users_by_role!

Это накладывает некоторые ограничения, например, использование в качестве QuerySet внутри DRF VIEW класса будет выглядеть следующим образом:

class ManagerPercentAdminView(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, SmartGenericViewSet):  
    def get_queryset(self):  
        return RoleDynamicLink.objects.get_users_by_role('manager')

    permission_classes = [PermissionAccess]  
    serializer_class = PercentSerializer

Необходимо переопределить метод get_queryset вместо того, чтобы указывать queryset, как атрибут класса. Это связано со спецификой обработки QuerySet в Django (если быть точнее это связанно со спецификой работы дескрипторов полей связи в django).