diff --git a/generic/forms.py b/generic/forms.py index 20d81691..cf56377b 100755 --- a/generic/forms.py +++ b/generic/forms.py @@ -593,77 +593,112 @@ class UserUserGroupForm(ModelForm): url = reverse("generic:user_search_widget") + # Build a small grade filter select + grades_options = '' + try: + from generic.models import UserGrades + grades_qs = UserGrades.objects.all() + for g in grades_qs: + grades_options += f'' + except Exception: + grades_options = '' + html = f""" -
+ """ return mark_safe(html) diff --git a/generic/models.py b/generic/models.py index c69d8740..c3a15775 100644 --- a/generic/models.py +++ b/generic/models.py @@ -1967,6 +1967,13 @@ class ExamCollection(models.Model, AuthorMixin): if UserUserGroup is None: raise RuntimeError("UserUserGroup model not available") + # Debug: log what we received + try: + group_pks = [g.pk for g in groups] if groups is not None else [] + except Exception: + group_pks = [] + logger.debug("bulk_add_user_user_groups called on collection=%s with groups=%s exam_types=%s", self.pk, group_pks, exam_types) + # Normalize groups to a list of model instances if groups is None: return 0 @@ -1994,9 +2001,21 @@ class ExamCollection(models.Model, AuthorMixin): for exam in exams: # Each exam model exposes a `user_user_groups` ManyToManyField try: + before_pks = set(exam.user_user_groups.values_list('pk', flat=True)) exam.user_user_groups.add(*groups_qs) # Ensure any downstream signals / caches see the change exam.save() + after_pks = set(exam.user_user_groups.values_list('pk', flat=True)) + # log if expected group pks are not present after add + try: + expected_pks = {g.pk for g in groups_qs} + except Exception: + expected_pks = set() + if not expected_pks.issubset(after_pks): + logger.warning( + "After add, exam %s missing expected user_user_groups; before=%s after=%s expected=%s", + getattr(exam, 'pk', exam), sorted(before_pks), sorted(after_pks), sorted(expected_pks), + ) updated += 1 except Exception as e: logger.exception("Failed to add user_user_groups to exam %s: %s", getattr(exam, 'pk', exam), e) @@ -2011,6 +2030,13 @@ class ExamCollection(models.Model, AuthorMixin): if CidUserGroup is None: raise RuntimeError("CidUserGroup model not available") + # Debug: log what we received + try: + group_pks = [g.pk for g in groups] if groups is not None else [] + except Exception: + group_pks = [] + logger.debug("bulk_add_cid_user_groups called on collection=%s with groups=%s exam_types=%s", self.pk, group_pks, exam_types) + if groups is None: return 0 @@ -2033,8 +2059,19 @@ class ExamCollection(models.Model, AuthorMixin): for exam in exams: # Each exam model exposes a `cid_user_groups` ManyToManyField try: + before_pks = set(exam.cid_user_groups.values_list('pk', flat=True)) exam.cid_user_groups.add(*groups_qs) exam.save() + after_pks = set(exam.cid_user_groups.values_list('pk', flat=True)) + try: + expected_pks = {g.pk for g in groups_qs} + except Exception: + expected_pks = set() + if not expected_pks.issubset(after_pks): + logger.warning( + "After add, exam %s missing expected cid_user_groups; before=%s after=%s expected=%s", + getattr(exam, 'pk', exam), sorted(before_pks), sorted(after_pks), sorted(expected_pks), + ) updated += 1 except Exception as e: logger.exception("Failed to add cid_user_groups to exam %s: %s", getattr(exam, 'pk', exam), e) diff --git a/generic/templates/generic/partials/user_search_widget_results.html b/generic/templates/generic/partials/user_search_widget_results.html index 5ea7b4d3..62ba7527 100644 --- a/generic/templates/generic/partials/user_search_widget_results.html +++ b/generic/templates/generic/partials/user_search_widget_results.html @@ -1,7 +1,7 @@ {% if results %} -