我正在为Django中的一所学校创建一个网络系统,为此,我决定将Django-Gurdian用于基于对象的权限,并且在迁移后设置一个信号来创建默认组,例如:all-students ,所有教师等...我正在使用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)
signals.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)
permission_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 谢谢。