diff --git a/CHANGELOG.rst b/CHANGELOG.rst index d05154a9ed55034bbef054f4463e67be35c65c27..7151f1d9b7d918f6cf56be6406f2924137694fec 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -21,6 +21,7 @@ Fixed ~~~~~ * The week overview page was not refreshed when a new week was selected in the dropdown. +* Make generation of full register printout faster. `2.0.1`_ - 2022-02-12 --------------------- diff --git a/aleksis/apps/alsijil/models.py b/aleksis/apps/alsijil/models.py index b8189119f601b4ba8348d6fff94dd6de0c8fa0a2..16d6c7d3e4c46ae17db133a981a17d965abe3da2 100644 --- a/aleksis/apps/alsijil/models.py +++ b/aleksis/apps/alsijil/models.py @@ -118,6 +118,14 @@ class RegisterObjectRelatedMixin(WeekRelatedMixin): else: return self.extra_lesson + @property + def register_object_key(self: Union["LessonDocumentation", "PersonalNote"]) -> str: + """Get a unique reference to the related object related.""" + if self.week and self.year: + return f"{self.register_object.pk}_{self.week}_{self.year}" + else: + return self.register_object.pk + @property def calendar_week(self: Union["LessonDocumentation", "PersonalNote"]) -> CalendarWeek: """Get the calendar week of this lesson documentation or personal note. diff --git a/aleksis/apps/alsijil/templates/alsijil/print/full_register.html b/aleksis/apps/alsijil/templates/alsijil/print/full_register.html index ab63dc7a7c9b44f9808d8c4af5460439ee7cdb8d..a8f7dd5c3d428c3e3d3e45324865cbd9fccab7f1 100644 --- a/aleksis/apps/alsijil/templates/alsijil/print/full_register.html +++ b/aleksis/apps/alsijil/templates/alsijil/print/full_register.html @@ -180,7 +180,7 @@ <div class="page-break"> </div> - {% if group.lessons.all %} + {% if lessons %} <h4>{% trans 'Teachers and lessons in group' %} {{ group.name }}</h4> <table id="lessons"> @@ -210,7 +210,7 @@ {% endif %} - {% if group.child_groups.all %} + {% if child_groups %} <h4>{% trans 'Teachers and lessons in child groups' %}</h4> <table id="lessons"> @@ -427,7 +427,7 @@ <tbody> {% for day in week %} {% with register_objects_by_day|get_dict:day as register_objects %} - {% for register_object, documentations, notes, substitution in register_objects %} + {% for register_object, documentation, notes, substitution in register_objects %} <tr class=" {% if substitution %} {% if substitution.cancelled %} @@ -461,47 +461,45 @@ </td> <td class="lesson-topic"> {% if register_object.label_ == "event" %} - {{ register_object.title }}: {{ documentations.0.topic }} + {{ register_object.title }}: {{ documentation.topic }} {% elif substitution.cancelled %} {% trans 'Lesson cancelled' %} {% else %} - {{ documentations.0.topic }} + {{ documentation.topic }} {% endif %} </td> - <td class="lesson-homework">{{ documentations.0.homework }}</td> + <td class="lesson-homework">{{ documentation.homework }}</td> <td class="lesson-notes"> - {{ documentations.0.group_note }} + {{ documentation.group_note }} {% for note in notes %} - {% if group in note.groups_of_person.all %} - {% if note.absent %} - <span class="lesson-note-absent"> - {{ note.person.last_name }}, {{ note.person.first_name|slice:"0:1" }}. - {% if note.excused %} - <span class="lesson-note-excused"> - {% if note.excuse_type %} - ({{ note.excuse_type.short_name }}) - {% else %} - ({% trans 'e' %}) - {% endif %} - </span> - {% endif %} - </span> - {% endif %} - {% if note.late %} - <span class="lesson-note-late"> - {{ note.person.last_name }}, {{ note.person.first_name|slice:"0:1" }}. - ({{ note.late }}′) - {% if note.excused %} - <span class="lesson-note-excused"> - {% if note.excuse_type %} - ({{ note.excuse_type.short_name }}) - {% else %} - ({% trans 'e' %}) - {% endif %} - </span> - {% endif %} - </span> - {% endif %} + {% if note.absent %} + <span class="lesson-note-absent"> + {{ note.person.last_name }}, {{ note.person.first_name|slice:"0:1" }}. + {% if note.excused %} + <span class="lesson-note-excused"> + {% if note.excuse_type %} + ({{ note.excuse_type.short_name }}) + {% else %} + ({% trans 'e' %}) + {% endif %} + </span> + {% endif %} + </span> + {% endif %} + {% if note.late %} + <span class="lesson-note-late"> + {{ note.person.last_name }}, {{ note.person.first_name|slice:"0:1" }}. + ({{ note.late }}′) + {% if note.excused %} + <span class="lesson-note-excused"> + {% if note.excuse_type %} + ({{ note.excuse_type.short_name }}) + {% else %} + ({% trans 'e' %}) + {% endif %} + </span> + {% endif %} + </span> {% endif %} {% for extra_mark in note.extra_marks.all %} <span> @@ -512,7 +510,7 @@ {% endfor %} </td> <td class="lesson-te"> - {% if documentations.0.topic %} + {% if documentation.topic %} {{ register_object.get_teachers.first.short_name }} {% endif %} </td> diff --git a/aleksis/apps/alsijil/views.py b/aleksis/apps/alsijil/views.py index 185c4c16e68a00a5499904b336c166fbfa05ccc3..8bbdd98d592699dcccdb805ab5555159389e8f72 100644 --- a/aleksis/apps/alsijil/views.py +++ b/aleksis/apps/alsijil/views.py @@ -622,16 +622,27 @@ def full_register_group(request: HttpRequest, id_: int) -> HttpResponse: | Q(event__groups__parent_groups=group) ) personal_notes = ( - PersonalNote.objects.select_related("lesson_period") - .prefetch_related( - "lesson_period__substitutions", "lesson_period__lesson__teachers", "groups_of_person" + PersonalNote.objects.prefetch_related( + "lesson_period__substitutions", "lesson_period__lesson__teachers" ) .not_empty() .filter(groups_q) + .filter(groups_of_person=group) ) - documentations = ( - LessonDocumentation.objects.select_related("lesson_period").not_empty().filter(groups_q) - ) + documentations = LessonDocumentation.objects.not_empty().filter(groups_q) + + sorted_documentations = {"extra_lesson": {}, "event": {}, "lesson_period": {}} + sorted_personal_notes = {"extra_lesson": {}, "event": {}, "lesson_period": {}, "person": {}} + for documentation in documentations: + key = documentation.register_object.label_ + sorted_documentations[key][documentation.register_object_key] = documentation + + for note in personal_notes: + key = note.register_object.label_ + sorted_personal_notes[key].setdefault(note.register_object_key, []) + sorted_personal_notes[key][note.register_object_key].append(note) + sorted_personal_notes["person"].setdefault(note.person.pk, []) + sorted_personal_notes["person"][note.person.pk].append(note) # Get all lesson periods for the selected group lesson_periods = LessonPeriod.objects.filter_group(group).distinct() @@ -645,8 +656,8 @@ def full_register_group(request: HttpRequest, id_: int) -> HttpResponse: register_objects_by_day.setdefault(day, []).append( ( extra_lesson, - list(filter(lambda d: d.extra_lesson == extra_lesson, documentations)), - list(filter(lambda d: d.extra_lesson == extra_lesson, personal_notes)), + sorted_documentations["extra_lesson"].get(extra_lesson.pk), + sorted_personal_notes["extra_lesson"].get(extra_lesson.pk, []), None, ) ) @@ -660,8 +671,8 @@ def full_register_group(request: HttpRequest, id_: int) -> HttpResponse: register_objects_by_day.setdefault(day, []).append( ( event_copy, - list(filter(lambda d: d.event == event, documentations)), - list(filter(lambda d: d.event == event, personal_notes)), + sorted_documentations["event"].get(event.pk), + sorted_personal_notes["event"].get(event.pk, []), None, ) ) @@ -680,26 +691,17 @@ def full_register_group(request: HttpRequest, id_: int) -> HttpResponse: <= day <= lesson_period.lesson.validity.date_end ): - filtered_documentations = list( - filter( - lambda d: d.week == week.week - and d.year == week.year - and d.lesson_period == lesson_period, - documentations, - ) + filtered_documentation = sorted_documentations["lesson_period"].get( + f"{lesson_period.pk}_{week.week}_{week.year}" ) - filtered_personal_notes = list( - filter( - lambda d: d.week == week.week - and d.year == week.year - and d.lesson_period == lesson_period, - personal_notes, - ) + filtered_personal_notes = sorted_personal_notes["lesson_period"].get( + f"{lesson_period.pk}_{week.week}_{week.year}", [] ) + substitution = lesson_period.get_substitution(week) register_objects_by_day.setdefault(day, []).append( - (lesson_period, filtered_documentations, filtered_personal_notes, substitution) + (lesson_period, filtered_documentation, filtered_personal_notes, substitution) ) persons = group.members.prefetch_related(None).select_related(None) @@ -707,7 +709,7 @@ def full_register_group(request: HttpRequest, id_: int) -> HttpResponse: prefetched_persons = [] for person in persons: - person.filtered_notes = list(filter(lambda d: d.person == person, personal_notes)) + person.filtered_notes = sorted_personal_notes["person"][person.pk] prefetched_persons.append(person) context["school_term"] = group.school_term @@ -722,15 +724,22 @@ def full_register_group(request: HttpRequest, id_: int) -> HttpResponse: context["today"] = date.today() context["lessons"] = ( group.lessons.all() + .select_related(None) + .prefetch_related(None) .select_related("validity", "subject") .prefetch_related("teachers", "lesson_periods") ) - context["child_groups"] = group.child_groups.all().prefetch_related( - "lessons", - "lessons__validity", - "lessons__subject", - "lessons__teachers", - "lessons__lesson_periods", + context["child_groups"] = ( + group.child_groups.all() + .select_related(None) + .prefetch_related(None) + .prefetch_related( + "lessons", + "lessons__validity", + "lessons__subject", + "lessons__teachers", + "lessons__lesson_periods", + ) ) return render_pdf(request, "alsijil/print/full_register.html", context)