Skip to content
Snippets Groups Projects
Commit a4ebb703 authored by Roang's avatar Roang
Browse files

Update FilteredListView with additional filters

- Add possibility to exclude by prepending filter wiht '!'
- Add capability to filter and exclude using Q expressions
- Add trace logging for query filters
parent e84b7ec3
Branches
Tags 6.10.6
No related merge requests found
import logging
import string import string
from typing import Any from typing import Any
...@@ -12,6 +13,8 @@ from django.views.generic import ListView ...@@ -12,6 +13,8 @@ from django.views.generic import ListView
from core.models.tags import TagItem from core.models.tags import TagItem
from core.paginators import AlphabetPaginator from core.paginators import AlphabetPaginator
logger = logging.getLogger(__name__)
class FilteredListView(ListView): class FilteredListView(ListView):
filters: dict[str, tuple[str, str]] | None = None filters: dict[str, tuple[str, str]] | None = None
...@@ -54,27 +57,40 @@ class FilteredListView(ListView): ...@@ -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 queryset = super().get_queryset() if queryset is None else queryset
ordering = self.get_ordering() ordering = self.get_ordering()
if ordering: if ordering:
if isinstance(ordering, str): if isinstance(ordering, str):
ordering = (ordering,) ordering = (ordering,)
queryset = queryset.order_by(*ordering) queryset = queryset.order_by(*ordering)
query_filters = {} query_filters = query_filters or {}
get_parameters = getattr(self.request, 'GET', {}) get_parameters = getattr(self.request, 'GET', {})
for parameter, (query_parameter, parameter_type) in self.filters.items(): for parameter, (query_parameter, parameter_type) in self.filters.items():
value: str | bool | list[str] value: str | bool | list[str]
if value := get_parameters.get(parameter, self.kwargs.get(parameter)): if value := get_parameters.get(parameter, self.kwargs.get(parameter)):
self.params[parameter] = str(value) self.params[parameter] = str(value)
match parameter_type: match parameter_type:
case 'bool':
value = value == 'true'
case 'list': case 'list':
value = value.split(',') value = value.split(',')
value = [x.strip() for x in value] value = [x.strip() for x in value]
query_filters[f'{query_parameter}__in'] = value
case 'bool':
value = value == 'true'
query_filters[query_parameter] = value
case _:
query_filters[query_parameter] = value query_filters[query_parameter] = value
queryset = queryset.filter(**query_filters) 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 return queryset
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment