Adding rebuil_tree command, breadcrumb and PrerequisiteClosure model/table
continuous-integration/drone/push Build is failing Details

This commit is contained in:
Gregory Trullemans 2022-01-12 21:03:43 +01:00
parent 83245b1216
commit d6c3df1c3b
3 changed files with 102 additions and 1 deletions

View File

@ -0,0 +1,44 @@
"""This command manages Closure Tables implementation
It adds new levels and cleans links between Educatives.
This way, it's relatively easy to fetch an entire tree with just one tiny request.
"""
from django.core.management.base import BaseCommand
from ultron.objective.models import Educative, PrerequisiteClosure
class Command(BaseCommand):
def handle(self, *args, **options):
# educative_list = Educative.objects.all()
educative_list = [Educative.objects.get(pk=44)]
for educative in educative_list:
# print('__________________________________________________________________________')
# print('Traitement de ' + str(educative))
# breadcrumb = [node for node in educative.breadcrumb()]
breadcrumb = educative.breadcrumb()
for path in range(0, len(breadcrumb)):
# print(' ˪ ' + str(path + 1) + 'ème chemin')
tree = set(PrerequisiteClosure.objects.filter(descendant=educative, path=path))
# print(' ' + str(tree))
for position, ancestor in enumerate(breadcrumb[path]):
# print(' ˪ Traitement de ' + str(ancestor.long_label) + ' : ' + str(ancestor.long_label) + ' -> ' + str(educative.long_label) + ' | ' + str(position) + ' | ' + str(path))
tree_path, _ = PrerequisiteClosure.objects.get_or_create(
ancestor=ancestor, descendant=educative, level=position, path=path
)
# if _:
# print(' -> CREATION : ' + str(tree_path))
# else:
# print(' -> RECUPERATION : ' + str(tree_path))
if tree_path in tree:
tree.remove(tree_path)
for tree_path in tree:
# print(' DELETE : ' + str(tree_path))
tree_path.delete()

View File

@ -78,6 +78,55 @@ class Educative(Markdownizable):
self.level,
self.difficulty,
)
def breadcrumb(self, path=[]):
"""
Renvoie le breadcrumb pour l'édutatif courant.
Exemple :
>>> s = Skill.objects.get(pk=44)
>>> s.breadcrumb()
"""
# print('________________________________________________________________')
# print(self)
path = path + [self]
if self.prerequisites.all().count() == 0:
# print('Plus d\'ancetres')
return [path]
# print('# ancetres : ' + str(self.prerequisites.all().count()))
path_list = []
for prerequisite in self.prerequisites.all():
# print(' ' + str(prerequisite))
# Permet de gérer les cas de récursivité (qui ne devraient pas se produire dans notre cas)
if prerequisite.id == self.id:
return [self]
new_paths = prerequisite.breadcrumb(path)
for new_path in new_paths:
path_list.append(new_path)
return path_list
class PrerequisiteClosure(models.Model):
"""
Closure table de prérequis
"""
class Meta:
unique_together = ("descendant", "ancestor", "level", "path")
descendant = models.ForeignKey(Educative, on_delete=models.CASCADE, related_name="ancestor")
ancestor = models.ForeignKey(Educative, on_delete=models.CASCADE, related_name="descendants")
level = models.PositiveIntegerField()
path = models.PositiveIntegerField()
def __str__(self):
return "%s -> %s (%s|%s)" % (
self.ancestor.long_label,
self.descendant.long_label,
self.level,
self.path
)
class TouchPosition(models.Model):

View File

@ -8,7 +8,12 @@ from django.urls import reverse
from ultron.people.models import Gymnast
from .forms import RoutineForm
from .models import Skill, Routine, RoutineSkill
from .models import (
Skill,
Routine,
RoutineSkill,
PrerequisiteClosure,
)
@login_required
@ -70,6 +75,9 @@ def skill_tree(request, skill_id):
"""
"""
skill = get_object_or_404(Skill, pk=skill_id)
print(skill)
skill_tree = PrerequisiteClosure.objects.filter(descendant=skill).order_by("path", "level")
print(skill_tree)
context = {"skill": skill}
return render(request, "objectives/skills/tree.html", context)