diff --git a/atlas/filters.py b/atlas/filters.py index 9daa9e95..7fc6bd54 100755 --- a/atlas/filters.py +++ b/atlas/filters.py @@ -1,4 +1,6 @@ import django_filters +from crispy_forms.helper import FormHelper +from crispy_forms.layout import Layout, Div from .models import ( Case, @@ -364,9 +366,10 @@ class NormalCaseFilter(django_filters.FilterSet): # Use the global Examination and Modality querysets from the Series model from generic.models import Examination, Modality - # Set up the actual querysets for the filters - self.base_filters.get("examination").queryset = Examination.objects.all() - self.base_filters.get("modality").queryset = Modality.objects.all() + # We'll set the actual querysets for the filters after applying + # any NormalCase queryset restrictions for the current user so + # that the choices only include examinations/modalities that + # actually have NormalCase records available. # If not an atlas editor restrict to cases authored by the user or open access cases if request is not None and not request.user.groups.filter(name="atlas_editor").exists(): @@ -376,8 +379,47 @@ class NormalCaseFilter(django_filters.FilterSet): queryset = NormalCase.objects.select_related("case") queryset = queryset.filter((Q(case__author__id=request.user.id) | Q(case__open_access=True))) + # Determine the NormalCase queryset we'll use to build choices + nc_qs = queryset if queryset is not None else NormalCase.objects.all() + + # Limit examination and modality choices to those present on the + # available NormalCase records (respecting user restrictions). + try: + exam_ids = nc_qs.values_list("examination_id", flat=True) + mod_ids = nc_qs.values_list("modality_id", flat=True) + self.base_filters.get("examination").queryset = Examination.objects.filter(id__in=exam_ids).distinct() + self.base_filters.get("modality").queryset = Modality.objects.filter(id__in=mod_ids).distinct() + except Exception: + # Fallback to all if something goes wrong + self.base_filters.get("examination").queryset = Examination.objects.all() + self.base_filters.get("modality").queryset = Modality.objects.all() + super(NormalCaseFilter, self).__init__(data=data, queryset=queryset, prefix=prefix, request=request) + # Attach a Crispy FormHelper to render the filter form as a + # horizontal Bootstrap grid. We set `form_tag=False` because the + # template already provides the