Commit 98e8da37 authored by Stanislas Guerra's avatar Stanislas Guerra Committed by Tim Graham
Browse files

Fixed #16311 -- Added a RelatedOnlyFieldListFilter class in admin.filters.

parent bf5382c6
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -242,6 +242,7 @@ answer newbie questions, and generally made Django that much better:
    Owen Griffiths
    Espen Grindhaug <http://grindhaug.org/>
    Mike Grouchy <http://mikegrouchy.com/>
    Stanislas Guerra <stan@slashdev.me>
    Janos Guljas
    Thomas Güttler <hv@tbz-pariv.de>
    Horst Gutmann <zerok@zerokspot.com>
+3 −2
Original line number Diff line number Diff line
@@ -6,7 +6,8 @@ from django.contrib.admin.options import (HORIZONTAL, VERTICAL,
    ModelAdmin, StackedInline, TabularInline)
from django.contrib.admin.filters import (ListFilter, SimpleListFilter,
    FieldListFilter, BooleanFieldListFilter, RelatedFieldListFilter,
    ChoicesFieldListFilter, DateFieldListFilter, AllValuesFieldListFilter)
    ChoicesFieldListFilter, DateFieldListFilter, AllValuesFieldListFilter,
    RelatedOnlyFieldListFilter)
from django.contrib.admin.sites import AdminSite, site
from django.utils.module_loading import autodiscover_modules

@@ -15,7 +16,7 @@ __all__ = [
    "StackedInline", "TabularInline", "AdminSite", "site", "ListFilter",
    "SimpleListFilter", "FieldListFilter", "BooleanFieldListFilter",
    "RelatedFieldListFilter", "ChoicesFieldListFilter", "DateFieldListFilter",
    "AllValuesFieldListFilter", "autodiscover",
    "AllValuesFieldListFilter", "RelatedOnlyFieldListFilter", "autodiscover",
]


+10 −1
Original line number Diff line number Diff line
@@ -170,7 +170,7 @@ class RelatedFieldListFilter(FieldListFilter):
        self.lookup_kwarg_isnull = '%s__isnull' % field_path
        self.lookup_val = request.GET.get(self.lookup_kwarg)
        self.lookup_val_isnull = request.GET.get(self.lookup_kwarg_isnull)
        self.lookup_choices = field.get_choices(include_blank=False)
        self.lookup_choices = self.field_choices(field, request, model_admin)
        super(RelatedFieldListFilter, self).__init__(
            field, request, params, model, model_admin, field_path)
        if hasattr(field, 'verbose_name'):
@@ -191,6 +191,9 @@ class RelatedFieldListFilter(FieldListFilter):
    def expected_parameters(self):
        return [self.lookup_kwarg, self.lookup_kwarg_isnull]

    def field_choices(self, field, request, model_admin):
        return field.get_choices(include_blank=False)

    def choices(self, cl):
        from django.contrib.admin.views.main import EMPTY_CHANGELIST_VALUE
        yield {
@@ -410,3 +413,9 @@ class AllValuesFieldListFilter(FieldListFilter):
            }

FieldListFilter.register(lambda f: True, AllValuesFieldListFilter)


class RelatedOnlyFieldListFilter(RelatedFieldListFilter):
    def field_choices(self, field, request, model_admin):
        limit_choices_to = {'pk__in': set(model_admin.get_queryset(request).values_list(field.name, flat=True))}
        return field.get_choices(include_blank=False, limit_choices_to=limit_choices_to)
+4 −3
Original line number Diff line number Diff line
@@ -726,7 +726,7 @@ class Field(RegisterLookupMixin):
    def get_validator_unique_lookup_type(self):
        return '%s__exact' % self.name

    def get_choices(self, include_blank=True, blank_choice=BLANK_CHOICE_DASH):
    def get_choices(self, include_blank=True, blank_choice=BLANK_CHOICE_DASH, limit_choices_to=None):
        """Returns choices with a default blank choices included, for use
        as SelectField choices for this field."""
        blank_defined = False
@@ -743,15 +743,16 @@ class Field(RegisterLookupMixin):
        if self.choices:
            return first_choice + choices
        rel_model = self.rel.to
        limit_choices_to = limit_choices_to or self.get_limit_choices_to()
        if hasattr(self.rel, 'get_related_field'):
            lst = [(getattr(x, self.rel.get_related_field().attname),
                   smart_text(x))
                   for x in rel_model._default_manager.complex_filter(
                       self.get_limit_choices_to())]
                       limit_choices_to)]
        else:
            lst = [(x._get_pk_val(), smart_text(x))
                   for x in rel_model._default_manager.complex_filter(
                       self.get_limit_choices_to())]
                       limit_choices_to)]
        return first_choice + lst

    def get_choices_default(self):
+14 −0
Original line number Diff line number Diff line
@@ -880,6 +880,20 @@ subclass::
                  ('is_staff', admin.BooleanFieldListFilter),
              )

      .. versionadded:: 1.8

      You can now limit the choices of a related model to the objects
      involved in that relation using ``RelatedOnlyFieldListFilter``::

          class BookAdmin(admin.ModelAdmin):
              list_filter = (
                  ('author', admin.RelatedOnlyFieldListFilter),
              )

      Assuming ``author`` is a ``ForeignKey`` to a ``User`` model, this will
      limit the ``list_filter`` choices to the users who have written a book
      instead of listing all users.

      .. note::

        The ``FieldListFilter`` API is considered internal and might be
Loading