-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- REmove old multi select
- Loading branch information
Showing
4 changed files
with
86 additions
and
195 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,85 +1,93 @@ | ||
"""Filter classes.""" | ||
from django.utils.translation import ugettext_lazy as _ | ||
from django.contrib.admin import SimpleListFilter | ||
from ..models import DummyModel | ||
|
||
|
||
class MultipleChoiceListFilter(SimpleListFilter): | ||
"""Filter class allowing multiple filter options.""" | ||
|
||
template = "multiselectlistfilter.html" | ||
|
||
def lookups(self, request, model_admin): | ||
"""Must be overridden to return a list of tuples (value, verbose value).""" | ||
raise NotImplementedError( | ||
"The MultipleChoiceListFilter.lookups() method must be overridden to " | ||
"return a list of tuples (value, verbose value)." | ||
) | ||
"""File containing filter classes and mixins.""" | ||
import urllib.parse | ||
from django.contrib import admin | ||
from django.db.models import Q | ||
from django.utils.translation import gettext_lazy as _ | ||
from django.contrib.admin.utils import reverse_field_path | ||
from django.core.exceptions import ValidationError | ||
from django.contrib.admin.options import IncorrectLookupParameters | ||
|
||
class MultiSelectMixin: | ||
"""Mixin for multi-select filters.""" | ||
|
||
def queryset(self, request, queryset): | ||
"""Return queryset based on selected parameters.""" | ||
if request.GET.get(self.parameter_name): | ||
kwargs = {self.parameter_name: request.GET[self.parameter_name].split(",")} | ||
queryset = queryset.filter(**kwargs) | ||
return queryset | ||
|
||
def value_as_list(self): | ||
"""Convert multiple filter fields to list.""" | ||
return self.value().split(",") if self.value() else [] | ||
"""Build queryset based on choices.""" | ||
params = Q() | ||
for lookup_arg, value in self.used_parameters.items(): | ||
params |= Q(**{lookup_arg: value}) | ||
try: | ||
return queryset.filter(params) | ||
except (ValueError, ValidationError) as e: | ||
# Fields may raise a ValueError or ValidationError when converting | ||
# the parameters to the correct type. | ||
raise IncorrectLookupParameters(e) | ||
|
||
def prepare_querystring_value(self, value): | ||
"""Preparse the query string value.""" | ||
# mask all commas or these values will be used | ||
# in a comma-seperated-list as get-parameter | ||
return str(value).replace(',', '%~') | ||
|
||
|
||
class FieldListMultiSelectFilter(MultiSelectMixin, admin.AllValuesFieldListFilter): | ||
"""Multi select dropdown filter for all kind of fields.""" | ||
|
||
template = 'multiselectdropdownfilter.html' | ||
|
||
def __init__(self, field, request, params, model, model_admin, field_path): | ||
self.lookup_kwarg = '%s__in' % field_path | ||
self.lookup_kwarg_isnull = '%s__isnull' % field_path | ||
lookup_vals = request.GET.get(self.lookup_kwarg) | ||
self.lookup_vals = lookup_vals.split(',') if lookup_vals else list() | ||
self.lookup_val_isnull = request.GET.get(self.lookup_kwarg_isnull) | ||
self.empty_value_display = model_admin.get_empty_value_display() | ||
parent_model, reverse_path = reverse_field_path(model, field_path) | ||
# Obey parent ModelAdmin queryset when deciding which options to show | ||
if model == parent_model: | ||
queryset = model_admin.get_queryset(request) | ||
else: | ||
queryset = parent_model._default_manager.all() | ||
self.lookup_choices = (queryset | ||
.distinct() | ||
.order_by(field.name) | ||
.values_list(field.name, flat=True)) | ||
super(admin.AllValuesFieldListFilter, self).__init__(field, request, params, model, model_admin, field_path) | ||
|
||
def choices(self, changelist): | ||
"""Overriden choices method.""" | ||
|
||
def amend_query_string(include=None, exclude=None): | ||
selections = self.value_as_list() | ||
if include and include not in selections: | ||
selections.append(include) | ||
if exclude and exclude in selections: | ||
selections.remove(exclude) | ||
if selections: | ||
csv = ",".join(selections) | ||
return changelist.get_query_string({self.parameter_name: csv}) | ||
else: | ||
return changelist.get_query_string(remove=[self.parameter_name]) | ||
|
||
"""Generate choices.""" | ||
add_facets = getattr(changelist, "add_facets", False) | ||
facet_counts = self.get_facet_queryset(changelist) if add_facets else None | ||
query_string = changelist.get_query_string({}, [self.lookup_kwarg, self.lookup_kwarg_isnull]) | ||
yield { | ||
"selected": self.value() is None, | ||
"query_string": changelist.get_query_string(remove=[self.parameter_name]), | ||
"display": "All", | ||
"reset": True, | ||
'selected': not self.lookup_vals and self.lookup_val_isnull is None, | ||
'query_string': query_string, | ||
'display': _('All'), | ||
} | ||
for lookup, title in self.lookup_choices: | ||
include_none = False | ||
count = None | ||
empty_title = self.empty_value_display | ||
for i, val in enumerate(self.lookup_choices): | ||
if add_facets: | ||
count = facet_counts[f"{i}__c"] | ||
if val is None: | ||
include_none = True | ||
empty_title = f"{empty_title} ({count})" if add_facets else empty_title | ||
continue | ||
|
||
val = str(val) | ||
qval = self.prepare_querystring_value(val) | ||
yield { | ||
"selected": str(lookup) in self.value_as_list(), | ||
"query_string": changelist.get_query_string( | ||
{self.parameter_name: lookup} | ||
), | ||
"include_query_string": amend_query_string(include=str(lookup)), | ||
"exclude_query_string": amend_query_string(exclude=str(lookup)), | ||
"display": title, | ||
'selected': qval in self.lookup_vals, | ||
'query_string': query_string, | ||
"display": f"{val} ({count})" if add_facets else val, | ||
'value': urllib.parse.quote_plus(val), | ||
'key': self.lookup_kwarg, | ||
} | ||
if include_none: | ||
yield { | ||
'selected': bool(self.lookup_val_isnull), | ||
'query_string': query_string, | ||
"display": empty_title, | ||
'value': 'True', | ||
'key': self.lookup_kwarg_isnull, | ||
} | ||
|
||
|
||
class DummyModelNameFilter(MultipleChoiceListFilter): | ||
"""Simple filter class to show records based on stt.""" | ||
|
||
title = _("Name") | ||
|
||
parameter_name = "name" | ||
|
||
def lookups(self, request, model_admin): | ||
"""Available options in dropdown.""" | ||
options = list() | ||
objs = DummyModel.objects.all() | ||
for obj in objs: | ||
name = obj.name | ||
options.append((name, name)) | ||
|
||
return options | ||
|
||
def queryset(self, request, queryset): | ||
"""Return queryset of records based on stt code(s).""" | ||
if self.value() is not None and queryset.exists(): | ||
names = self.value().split(",") | ||
queryset = queryset.filter(name__in=names) | ||
return queryset |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.