diff --git a/atlas/filters.py b/atlas/filters.py index eace4288..104d0341 100755 --- a/atlas/filters.py +++ b/atlas/filters.py @@ -109,6 +109,12 @@ class CaseFilter(django_filters.FilterSet): # Free-text search to help find the correct examination when there are # many similarly-named Series/Examination entries. examination_text = django_filters.CharFilter(method='filter_examination_text', label='Examination (text)') + # Full list of conditions and a text search to find conditions + condition = django_filters.ModelMultipleChoiceFilter( + queryset=Condition.objects.all(), + label='Condition', + ) + condition_text = django_filters.CharFilter(method='filter_condition_text', label='Condition (text)') differential_case = django_filters.ModelMultipleChoiceFilter( label="Differential", field_name="differentialcase__condition", @@ -173,6 +179,28 @@ class CaseFilter(django_filters.FilterSet): return queryset.filter(series__examination__in=matches).distinct() + def filter_condition_text(self, queryset, name, value): + """Filter Cases by a text search on related Condition records. + + Matches both direct `condition` M2M and `differential` entries. + """ + if not value: + return queryset + + # Only try PK match when numeric + try: + pk_val = int(value) + except Exception: + pk_val = None + + if pk_val is not None: + matches = Condition.objects.filter(Q(name__icontains=value) | Q(pk=pk_val)).distinct() + else: + matches = Condition.objects.filter(Q(name__icontains=value)).distinct() + + # Match either direct condition M2M or differential (through Differential) + return queryset.filter(Q(condition__in=matches) | Q(differential__in=matches)).distinct() + class SeriesFilter(django_filters.FilterSet): case = django_filters.ModelMultipleChoiceFilter(