diff --git a/program/filters.py b/program/filters.py index b588795aea8207b11544b48008529fd865d81ae6..6b645a100a216de6b30597b9689adc0eec741ff9 100644 --- a/program/filters.py +++ b/program/filters.py @@ -1,10 +1,11 @@ import datetime +from django_filters import constants from django_filters import rest_framework as filters from django_filters import widgets from django import forms -from django.db.models import Q, QuerySet +from django.db.models import Exists, OuterRef, Q, QuerySet from django.utils import timezone from program import models @@ -38,9 +39,25 @@ class IntegerInFilter(filters.BaseInFilter): super().__init__(*args, **kwargs) +class ShowOrderingFilter(filters.OrderingFilter): + def filter(self, qs: QuerySet, value): + if value in constants.EMPTY_VALUES: + return qs + ordering = [self.get_ordering_value(param) for param in value] + fields = (field.lstrip("-") for field in ordering) + if "is_owner" in fields: + _id = getattr(self.parent.request.user, "id", None) + qs = qs.annotate( + is_owner=Exists( + models.Show.owners.through.objects.filter(user=_id, show=OuterRef("pk")), + ) + ) + return qs.order_by(*ordering) + + class ShowFilterSet(StaticFilterHelpTextMixin, filters.FilterSet): - order = filters.OrderingFilter( - fields=["name", "id", "is_active", "is_owner"], + order = ShowOrderingFilter( + fields=["name", "slug", "id", "is_active", "is_owner"], help_text="Order shows by the given field(s).", ) category_ids = IntegerInFilter( @@ -100,11 +117,6 @@ class ShowFilterSet(StaticFilterHelpTextMixin, filters.FilterSet): help_text="Return only shows of the given type slug.", ) - def filter_queryset(self, queryset): - _id = getattr(self.request.user, "id", None) - queryset = queryset.annotate(is_owner=Q(owners=_id)) - return super().filter_queryset(queryset) - def filter_active(self, queryset: QuerySet, name: str, value: bool): # Filter currently running shows # Get currently running schedules to filter by first