Skip to content

Instantly share code, notes, and snippets.

@vdboor
Last active December 13, 2016 14:00
Show Gist options
  • Save vdboor/451a813b9e3ea622a399cd67d607f69d to your computer and use it in GitHub Desktop.
Save vdboor/451a813b9e3ea622a399cd67d607f69d to your computer and use it in GitHub Desktop.
In the admin sidebar, only show related objects that are in use by the objects shown in the list
from django.contrib import admin
from django.contrib.admin.utils import get_model_from_relation
from django.utils.encoding import smart_text
class LimitedRelatedFieldListFilter(admin.RelatedFieldListFilter):
"""
Limit the filter choices in the admin sidebar to objects
which are actually used by the objects shown in the list.
Usage::
list_filter = (
('fieldname', LimitedRelatedFieldListFilter),
)
"""
def __init__(self, field, request, params, model, model_admin, field_path):
# NOTE:
# Replaced the entire __init__ code,
# to offer a get_queryset() hook that allows limiting the queryset.
other_model = get_model_from_relation(field)
if hasattr(field, 'rel'):
rel_name = field.rel.get_related_field().name
else:
rel_name = other_model._meta.pk.name
self.lookup_kwarg = '%s__%s__exact' % (field_path, rel_name)
self.lookup_kwarg_isnull = '%s__isnull' % field_path
self.lookup_val = request.GET.get(self.lookup_kwarg, None)
self.lookup_val_isnull = request.GET.get(
self.lookup_kwarg_isnull, None)
self.lookup_choices = [
(x._get_pk_val(), smart_text(x)) for x in self.get_queryset(field)
]
admin.FieldListFilter.__init__(
self, field, request, params, model, model_admin, field_path)
if hasattr(field, 'verbose_name'):
self.lookup_title = field.verbose_name
else:
self.lookup_title = other_model._meta.verbose_name
self.title = self.lookup_title
self.empty_value_display = model_admin.get_empty_value_display()
def get_queryset(self, field):
# Allow filtering the queryset!
other_model = get_model_from_relation(field)
return other_model._default_manager.complex_filter(field.rel.limit_choices_to)
class SortedLimitedRelatedFieldListFilter(LimitedRelatedFieldListFilter):
"""
Override the standard RelatedField list filter, to sort the values.
Usage::
list_filter = (
('fieldname', SortedLimitedRelatedFieldListFilter),
)
"""
def __init__(self, *args, **kwargs):
super(SortedLimitedRelatedFieldListFilter, self).__init__(*args, **kwargs)
self.lookup_choices = sorted(self.lookup_choices, key=lambda a: a[1].lower())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment