Repository: e-valuation/EvaP

Issue:
Refresh results page cache on changes
When these (and possibly a few other) things are changed, the results page cache has to be refreshed:
- course name
- semester name
- degree name
- course type name
- course's responsible


Discussion:
course name and course's responsible should not be editable for published courses, and the results are only cached for courses that are published. or did i get something wrong?
Yes, that's right

Resolving patch:
diff --git a/evap/results/views.py b/evap/results/views.py
--- a/evap/results/views.py
+++ b/evap/results/views.py
@@ -23,6 +23,10 @@ def get_course_result_template_fragment_cache_key(course_id, language, can_user_
 
 def delete_template_cache(course):
     assert course.state != 'published'
+    _delete_template_cache_impl(course)
+
+
+def _delete_template_cache_impl(course):
     caches['results'].delete(get_course_result_template_fragment_cache_key(course.id, 'en', True))
     caches['results'].delete(get_course_result_template_fragment_cache_key(course.id, 'en', False))
     caches['results'].delete(get_course_result_template_fragment_cache_key(course.id, 'de', True))
@@ -49,6 +53,13 @@ def warm_up_template_cache(courses):
         translation.activate(current_language)  # reset to previously set language to prevent unwanted side effects
 
 
+def update_template_cache(courses):
+    for course in courses:
+        assert course.state == "published"
+        _delete_template_cache_impl(course)
+        warm_up_template_cache([course])
+
+
 def get_courses_with_prefetched_data(courses):
     if isinstance(courses, QuerySet):
         participant_counts = courses.annotate(num_participants=Count("participants")).values_list("num_participants", flat=True)
diff --git a/evap/staff/forms.py b/evap/staff/forms.py
--- a/evap/staff/forms.py
+++ b/evap/staff/forms.py
@@ -13,6 +13,7 @@
 from evap.evaluation.models import (Contribution, Course, CourseType, Degree, EmailTemplate, FaqQuestion, FaqSection, Question, Questionnaire,
                                     RatingAnswerCounter, Semester, TextAnswer, UserProfile)
 from evap.evaluation.tools import date_to_datetime
+from evap.results.views import update_template_cache
 
 logger = logging.getLogger(__name__)
 
@@ -84,6 +85,12 @@ class Meta:
         model = Semester
         fields = ("name_de", "name_en", "short_name_de", "short_name_en")
 
+    def save(self, *args, **kwargs):
+        semester = super().save(*args, **kwargs)
+        if 'short_name_en' in self.changed_data or 'short_name_de' in self.changed_data:
+            update_template_cache(semester.courses.filter(state="published"))
+        return semester
+
 
 class DegreeForm(forms.ModelForm):
     def __init__(self, *args, **kwargs):
@@ -100,6 +107,12 @@ def clean(self):
         if self.cleaned_data.get('DELETE') and not self.instance.can_manager_delete:
             raise SuspiciousOperation("Deleting degree not allowed")
 
+    def save(self, *args, **kwargs):
+        degree = super().save(*args, **kwargs)
+        if "name_en" in self.changed_data or "name_de" in self.changed_data:
+            update_template_cache(degree.courses.filter(state="published"))
+        return degree
+
 
 class CourseTypeForm(forms.ModelForm):
     def __init__(self, *args, **kwargs):
@@ -116,6 +129,12 @@ def clean(self):
         if self.cleaned_data.get('DELETE') and not self.instance.can_manager_delete:
             raise SuspiciousOperation("Deleting course type not allowed")
 
+    def save(self, *args, **kwargs):
+        course_type = super().save(*args, **kwargs)
+        if "name_en" in self.changed_data or "name_de" in self.changed_data:
+            update_template_cache(course_type.courses.filter(state="published"))
+        return course_type
+
 
 class CourseTypeMergeSelectionForm(forms.Form):
     main_type = forms.ModelChoiceField(CourseType.objects.all())


Test patch: