Skip to content

Commit

Permalink
Add MultiSelectRelatedFieldListFilter
Browse files Browse the repository at this point in the history
  • Loading branch information
JobDoesburg committed Jun 1, 2023
1 parent bd85e70 commit fe32832
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 6 deletions.
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "django-admin-multi-select-filter"
version = "1.1.0"
version = "1.2.0"
description = "Django admin filter for multiple select"
readme = "README.md"
authors = [{ name = "Job Doesburg", email = "[email protected]" }]
Expand Down
57 changes: 52 additions & 5 deletions src/django_admin_multi_select_filter/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,12 @@ def __init__(self, field, request, params, model, model_admin, field_path):
# Obey parent ModelAdmin queryset when deciding which options to show
if model == parent_model:
queryset = model_admin.get_queryset(request)
self.lookup_choices = (
queryset.distinct().order_by(field.name).values_list(field.name, flat=True)
)
else:
queryset = parent_model._default_manager.all()
self.lookup_choices = queryset.distinct()

self.lookup_choices = (
queryset.distinct().order_by(field.name).values_list(field.name, flat=True)
)

def expected_parameters(self):
return [self.lookup_kwarg, self.lookup_kwarg_isnull]

Expand Down Expand Up @@ -76,3 +75,51 @@ def choices(self, changelist):
),
"display": self.empty_value_display,
}


class MultiSelectRelatedFieldListFilter(admin.RelatedFieldListFilter):
def __init__(self, field, request, params, model, model_admin, field_path):
super().__init__(field, request, params, model, model_admin, field_path)
self.lookup_kwarg = "%s__%s__in" % (field_path, field.target_field.name)
self.lookup_kwarg_isnull = "%s__isnull" % field_path
values = params.get(self.lookup_kwarg, [])
self.lookup_val = values.split(",") if values else []
self.lookup_choices = self.field_choices(field, request, model_admin)

def choices(self, changelist):
yield {
"selected": self.lookup_val is None and not self.lookup_val_isnull,
"query_string": changelist.get_query_string(
remove=[self.lookup_kwarg, self.lookup_kwarg_isnull]
),
"display": _("All"),
}

for pk_val, val in self.lookup_choices:
if val is None:
self.include_empty_choice = True
continue
val = str(val)

if str(pk_val) in self.lookup_val:
values = [str(v) for v in self.lookup_val if str(v) != str(pk_val)]
else:
values = self.lookup_val + [str(pk_val)]

yield {
"selected": self.lookup_val is not None
and str(pk_val) in self.lookup_val,
"query_string": changelist.get_query_string(
{self.lookup_kwarg: ",".join(values)}, [self.lookup_kwarg_isnull]
),
"display": val,
}
empty_title = self.empty_value_display
if self.include_empty_choice:
yield {
"selected": bool(self.lookup_val_isnull),
"query_string": changelist.get_query_string(
{self.lookup_kwarg_isnull: "True"}, [self.lookup_kwarg]
),
"display": empty_title,
}

0 comments on commit fe32832

Please sign in to comment.