Я создаю веб-систему для школы в Джанго, для чего я решил, что буду использовать Джанго-Гурдиан для разрешений на основе объектов, а также настроил сигнал после миграции для создания групп по умолчанию, таких как: 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
Спасибо.