diff --git a/src/core/views/list_views.py b/src/core/views/list_views.py index e5f1bc614fe0b102d87688c78e8772e562edb87b..da8d19277b70f8e67bb637675ce990a2565e6202 100644 --- a/src/core/views/list_views.py +++ b/src/core/views/list_views.py @@ -1,3 +1,4 @@ +import logging import string from typing import Any @@ -12,6 +13,8 @@ from django.views.generic import ListView from core.models.tags import TagItem from core.paginators import AlphabetPaginator +logger = logging.getLogger(__name__) + class FilteredListView(ListView): filters: dict[str, tuple[str, str]] | None = None @@ -54,27 +57,40 @@ class FilteredListView(ListView): }, } - def get_queryset(self, queryset: QuerySet | None = None) -> QuerySet[Any]: + def get_queryset(self, queryset: QuerySet | None = None, query_filters: dict[str, str | list | bool] | None = None) -> QuerySet[Any]: queryset = super().get_queryset() if queryset is None else queryset ordering = self.get_ordering() if ordering: if isinstance(ordering, str): ordering = (ordering,) queryset = queryset.order_by(*ordering) - query_filters = {} + query_filters = query_filters or {} get_parameters = getattr(self.request, 'GET', {}) for parameter, (query_parameter, parameter_type) in self.filters.items(): value: str | bool | list[str] if value := get_parameters.get(parameter, self.kwargs.get(parameter)): self.params[parameter] = str(value) match parameter_type: - case 'bool': - value = value == 'true' case 'list': value = value.split(',') value = [x.strip() for x in value] - query_filters[query_parameter] = value - queryset = queryset.filter(**query_filters) + query_filters[f'{query_parameter}__in'] = value + case 'bool': + value = value == 'true' + query_filters[query_parameter] = value + case _: + query_filters[query_parameter] = value + logger.trace(f'Query Filters: {query_filters}') + for key, value in query_filters.items(): + match key[0]: + case '!': + queryset = queryset.exclude(**{key[1:]: value}) + case 'X': + queryset = queryset.exclude(value) + case 'Q': + queryset = queryset.filter(value) + case _: + queryset = queryset.filter(**{key: value}) return queryset