Как исправить 'Запрос на сопоставление разрешений не существует.'в Джанго - PullRequest
0 голосов
/ 18 апреля 2019

Я создаю веб-систему для школы в Джанго, для чего я решил, что буду использовать Джанго-Гурдиан для разрешений на основе объектов, а также настроил сигнал после миграции для создания групп по умолчанию, таких как: all-ученики , все учителя и т.д ... И я запускаю тесты с Pytest, , но когда я запускаю их по какой-то причине, все швы разрешений исчезают.

Это самый первый проект такого масштаба, который я делаю, и я создаю его, чтобы узнать немного больше. Это также мой первый вопрос на этом сайте. Извините, но многие комментарии и переменные и т. Д. Написаны на португальском языке или смешаны с английским. Я могу предоставить перевод, если вам это нужно. И я знаю, что большая часть кода, вероятно, написана плохо, поскольку я сказал, что все еще учусь.

Я пробовал нормальный сервер, но ничего не шло не так. Когда я мигрирую из терминала, все в порядке. Я запускаю его в Windows 10, используя PyCharm для запуска. Я использую Python 3.7, Django 2.1.8, django-guardian 1.5.0, pytest 4.2.0.

apps.py - Регистрация сигнала

class EscolaConfig(AppConfig):
     name = 'escola'

     def ready(self):
         from django.db.models.signals import post_migrate
         from .signals import populate_models
         post_migrate.connect(populate_models, sender=self)

signal.py - Создание групп

INITIAL_GROUPS = {
    'Admin': [
              'escola.add_turma',
              'escola.add_aluno',
              'escola.can_add_aluno',
              'escola.mudar_horario',
              'escola.can_populate_turma',
              ],
    'Todos_Alunos': [],
}
def populate_models(sender, **kwargs):
    from django.apps import apps
    from django.contrib.auth.management import create_permissions

    for app_config in apps.get_app_configs():
        app_config.models_module = True
        create_permissions(app_config, verbosity=0)
        app_config.models_module = None

    from django.contrib.auth.models import Group, Permission
    from escola.permission_utils import permission_names_to_objects

    logger.info("Iniciando modulo, para adição de Itens pós migrate.")
    logger.info("Iniciando verificação de grupos:")
    for g in INITIAL_GROUPS.keys():
        group, created = Group.objects.get_or_create(name=g)
        if created:
            logger.info(f"Criado grupo {g}.")
        else:
            logger.info(f"Grupo {g} já existe.")

        logger.info(f"Iniciando metodo de dar Permissões para o grupo {g}")
        logger.debug(f"Permissões a serem dadas:{INITIAL_GROUPS[g]}")
        perms_to_add = permission_names_to_objects(INITIAL_GROUPS[g])
        logger.info(f"Dando permissões {perms_to_add.__str__()} para o grupo {g}")
        group.permissions.add(*perms_to_add)

allow_utils.py - получить объект разрешения по имени

def permission_names_to_objects(names):
    """
    Given an iterable of permission names (e.g. 'app_label.add_model'),
    return an iterable of Permission objects for them.  The permission
    must already exist, because a permission name is not enough information
    to create a new permission.
    """
    result = []
    for name in names:
        name: str
        app_label, codename = name.split(".", 1)
        # Is that enough to be unique? Hope so
        try:
            result.append(Permission.objects.get(content_type__app_label=app_label,
                                                 codename=codename))
        except Permission.DoesNotExist:
            logger.error("NO SUCH PERMISSION: %s, %s" % (app_label, codename))
    return result

models.py

[...]
class Turma(models.Model, ExportModelOperationsMixin('Turma')):
    """ Uma turma, conjunto de alunos, materias, tarefas, tambem possui um horario"""
    numero = models.IntegerField()
    ano = models.IntegerField()
    lider = models.ForeignKey(Group, on_delete=models.DO_NOTHING, null=True, blank=True, related_name='turma_lider')
    vicelider = models.ForeignKey(Group, on_delete=models.DO_NOTHING, null=True, blank=True, related_name='turma_vicelider')
    regente = models.ForeignKey(Group, on_delete=models.DO_NOTHING, null=True, blank=True, related_name='turma_regente')

    class Meta:
        """Meta das Models"""
        permissions = (
            ('can_populate_turma', "Pode popular turmas"                ),
            ('can_add_aluno'     , "Pode adicionar um aluno a turma."   ),
            ('mudar_horario'     , "Pode editar o horario."             ),
            ('can_add_materia'   , 'Pode adicionar uma materia a turma.'),
            ('can_add_tarefa'    , "Pode adicionar uma tarefa."         ),
        )

    def get_or_create_lider_group(self):
        """Retorna o grupo de lider, que deve possuir apenas um usuario."""
        if not self.lider:
            logging.info(Group.objects.filter(name=f'lider_turma_{self.pk}'))
            logging.info(len(Group.objects.filter(name=f'lider_turma_{self.pk}')))
            if not len(Group.objects.filter(name=f'lider_turma_{self.pk}')) == 0:
                self.lider = Group.objects.get(name=f'lider_turma_{self.pk}')
            else:
                self.lider = Group.objects.create(name=f'lider_turma_{self.pk}')
        assign_perm('escola.mudar_horario', self.lider, obj=self)
        assign_perm('escola.can_add_materia', self.lider, obj=self)
        assign_perm('escola.can_add_tarefa', self.lider, obj=self)
        return self.lider

    def get_or_create_vicelider_group(self):
        """Retorna o grupo de vicelider, que deve ter apenas um usuario."""
        if not self.vicelider:
            logging.info(Group.objects.filter(name=f'vicelider_turma_{self.pk}'))
            logging.info(len(Group.objects.filter(name=f'vicelider_turma_{self.pk}')))
            if len(Group.objects.filter(name=f'vicelider_turma_{self.pk}').all()) != 0:
                self.vicelider = Group.objects.get(name=f'vicelider_turma_{self.pk}')
            else:
                self.vicelider = Group.objects.create(name=f'vicelider_turma_{self.pk}')
        assign_perm('escola.mudar_horario', self.vicelider, obj=self)
        assign_perm('escola.can_add_materia', self.vicelider, obj=self)
        assign_perm('escola.can_add_tarefa', self.vicelider, obj=self)
        return self.vicelider

    def get_or_create_regente_group(self):
        """ Retorna o grupo de regente, que deve ter apenas um usuario. """
        if not self.regente:
            logging.info(f"Grupos regente da turma:{Group.objects.filter(name=f'regente_turma_{self.pk}')}")
            logging.info(f"QNT:{len(Group.objects.filter(name=f'regente_turma_{self.pk}'))}")
            if len(Group.objects.filter(name=f'regente_turma_{self.pk}')) > 0:
                self.regente = Group.objects.get(name=f'regente_turma_{self.pk}')
            else:
                self.regente = Group.objects.create(name=f'regente_turma_{self.pk}')
        logging.info(permission_names_to_objects(['escola.can_add_aluno',
                                                  'escola.mudar_horario',
                                                  'escola.can_add_materia',
                                                  'escola.can_add_tarefa']))
        assign_perm('escola.can_add_aluno', self.regente, obj=self)
        assign_perm('escola.mudar_horario', self.regente, obj=self)
        assign_perm('escola.can_add_materia', self.regente, obj=self)
        assign_perm('escola.can_add_tarefa', self.regente, obj=self)
        return self.regente

[...]

Ошибка, о которой я упоминал, возникла в вышеупомянутых assign_perm ().

tests / test_views.py - один из тестов, выдающих ошибку

    def test_create_with_valid(self):
        c = Client()
        admin = create_admin()
        c.force_login(admin)
        profe = create_professor()
        turma__pk = create_turma().pk
        response = c.post(reverse('escola:add-cargo', args=[turma__pk, ]),
                          {'nome': 'Regencia', 'ocupante': profe.user.pk.__str__(),
                           'cod_especial': '5', 'ativo': 'True'})
        self.assertRedirects(response, reverse('escola:list-cargos', args=[turma__pk, ]))

        cargo_criado: CargoTurma = CargoTurma.objects.get(nome='Regencia')
        assert cargo_criado.turma is not None
        assert cargo_criado.nome == 'Regencia'
        assert cargo_criado.ativo is True
        assert cargo_criado.cod_especial == 5
        assert cargo_criado.ocupante == profe.user

tests / helpers / utils.py - Утилиты для тестов.



def create_admin():
    user = mixer.blend(User, is_superuser=True)
    return user


def create_aluno(turma=None, user=None):
    if not turma:
        turma = mixer.blend(Turma)
    if user is None:
        user = mixer.blend(User)
    profile = mixer.blend(Profile, user=user, is_aluno=True, is_professor=False)
    aluno = mixer.blend(Aluno, user=user)
    return aluno


def create_professor():
    user = mixer.blend(User)
    profile = mixer.blend(Profile, user=user, is_aluno=False, is_professor=True)
    professor = mixer.blend(Professor, user=user)
    return professor


def create_turma():
    turma = mixer.blend(Turma, ano=datetime.today().year)
    horario = mixer.blend(Horario, turma=turma)
    aluno = create_aluno(turma=turma)
    prof = create_professor()
    materia = mixer.blend(MateriaDaTurma, professor=prof, turma=turma)
    return turma

И, наконец, код, который его сломал, после того, как я создал этот файл, ошибки появились впервые: user_utils.py - Утилиты для моего приложения, при создании определенного типа пользователя


def create_user(username, password, **kwargs) -> User:
    """
    Cria um usuario com esses dados
    :param username: Nome de usuario
    :param password: Senha
    :param kwargs: Veja abaixo...
    :keyword email:
        Opicional email do usuario
    :return: Usuario Criado
    :rtype User
    """
    u = User.objects.create_user(username, password=password, email=kwargs.get('email'))
    p = Profile(user=u)
    p.is_professor = False
    p.is_aluno = False
    p.save()
    return u


def give_admin(user: User) -> None:
    """
    Transforma o usuario em admin;
    :param User user:
    :return: None
    """
    user.is_staff = True
    user.groups.add(get_admin_group())
    user.save()


def create_admin_user(username: str, password: str, *args, **kwargs) -> User:
    """
    Cria um usuario com status de admin.
    :param username: Nome de usuario para ele
    :param password: Senha
    :keyword email:
        Opicional, email da conta a ser criada
    :return: Usuario criado
    :rtype: User
    """
    user = User.objects.create_user(username, password=password, email=kwargs.get('email'))
    give_admin(user)
    return user


def get_admin_group() -> Group:
    """
    Pega ou cria o grupo de Admins
    :return: Grupo de Admins
    :rtype: Group
    LOGS:"Por algum motivo o Grupo admin não havia sido criado." se um Grupo ainda não tiver sido criado,
    o que não deveria acontecer, já que esse grupo é criado após os migrates.
    """
    g, c = Group.objects.get_or_create(name="Admin")
    if c:
        logger.warning("Por algum motivo o Grupo admin não havia sido criado.")
    return g


def create_aluno_user(username, senha, turma: Turma, nome, *args, **kwargs):
    """
    Cria um usuario como aluno
    :param username: Nome de usuario
    :param senha: senha
    :param turma: Turma do aluno
    :param nome: Nome completo do aluno
    :keyword n_chamda: Numero da chmada do aluno.
    :return:
    """
    u = create_user(username, senha)
    p = u.profile_escola
    p.is_aluno = True
    p.save()
    a = Aluno()
    a.user = u
    a.turma = turma
    a.nome = nome
    if kwargs.get('n_chamda'):
        a.chamada = kwargs.get('n_chamda')
    a.save()
    u.groups.add(get_all_alunos_group())
    u.groups.add(get_turma_alunos_group(turma.pk))
    return u


def get_all_alunos_group():
    g, created = Group.objects.get_or_create(name='Todos_Alunos')
    return g


def get_turma_alunos_group(turma_pk):
    g, created = Group.objects.get_or_create(name=f'Alunos_{turma_pk}')
    return g


def create_professor_user(username, password, name):
    u = create_user(username, password)
    p = u.profile_escola
    p.is_professor = True
    u.groups.add(get_all_professor_group())
    P = Professor()
    P.user = u
    P.nome = name
    return u


def get_all_professor_group():
    g, created = Group.objects.get_or_create(name='Todos_Professor')
    return g

Я ожидал, что функции получат группы студентов из Turma (класса), но когда я запускаю тесты, все разрешения из модели исчезают Если вам нужна дополнительная информация, не бойтесь спрашивать или искать ее в репозитории GitHub: https://github.com/vini84200/medusa2/tree/a72752252d57f9e2fdf12851e88e6d82390f38e4 Или в журналах испытаний: https://travis -ci.org / vini84200 / medusa2 / jobs / 521532783 Спасибо.

...