Ticket #16311: patch_list_filter_limit_to_related_with_tests.diff

File patch_list_filter_limit_to_related_with_tests.diff, 6.5 KB (added by Stanislas Guerra <stan@…>, 13 years ago)

Regresssion tests added.

  • django/db/models/fields/__init__.py

     
    355355    def get_validator_unique_lookup_type(self):
    356356        return '%s__exact' % self.name
    357357
    358     def get_choices(self, include_blank=True, blank_choice=BLANK_CHOICE_DASH):
     358    def get_choices(self, include_blank=True, blank_choice=BLANK_CHOICE_DASH, limit_choices_to=None):
    359359        """Returns choices with a default blank choices included, for use
    360360        as SelectField choices for this field."""
    361361        first_choice = include_blank and blank_choice or []
    362362        if self.choices:
    363363            return first_choice + list(self.choices)
    364364        rel_model = self.rel.to
     365        limit_choices_to = limit_choices_to and limit_choices_to or self.rel.limit_choices_to
    365366        if hasattr(self.rel, 'get_related_field'):
    366             lst = [(getattr(x, self.rel.get_related_field().attname), smart_unicode(x)) for x in rel_model._default_manager.complex_filter(self.rel.limit_choices_to)]
     367            lst = [(getattr(x, self.rel.get_related_field().attname), smart_unicode(x)) for x in rel_model._default_manager.complex_filter(limit_choices_to)]
    367368        else:
    368             lst = [(x._get_pk_val(), smart_unicode(x)) for x in rel_model._default_manager.complex_filter(self.rel.limit_choices_to)]
     369            lst = [(x._get_pk_val(), smart_unicode(x)) for x in rel_model._default_manager.complex_filter(limit_choices_to)]
    369370        return first_choice + lst
    370371
    371372    def get_choices_default(self):
  • django/contrib/admin/filters.py

     
    160160        self.lookup_val = request.GET.get(self.lookup_kwarg, None)
    161161        self.lookup_val_isnull = request.GET.get(
    162162                                      self.lookup_kwarg_isnull, None)
    163         self.lookup_choices = field.get_choices(include_blank=False)
     163        self.lookup_choices = self.field_choices(field, request, model_admin)
    164164        self.title = self.lookup_title
    165165
    166166    def has_output(self):
     
    175175    def used_params(self):
    176176        return [self.lookup_kwarg, self.lookup_kwarg_isnull]
    177177
     178    def field_choices(self, field, request, model_admin):
     179        return field.get_choices(include_blank=False)
     180
    178181    def choices(self, cl):
    179182        from django.contrib.admin.views.main import EMPTY_CHANGELIST_VALUE
    180183        yield {
     
    399402            }
    400403
    401404FieldListFilter.register(lambda f: True, AllValuesFieldListFilter)
     405
     406
     407class RelatedOnlyFieldListFilter(RelatedFieldListFilter):
     408    def field_choices(self, field, request, model_admin):
     409        limit_choices_to = {'pk__in': set(model_admin.queryset(request).values_list(field.name, flat=True))}
     410        return field.get_choices(include_blank=False, limit_choices_to=limit_choices_to)
  • tests/regressiontests/admin_filters/tests.py

     
    1010from django.contrib.auth.models import User
    1111from django.contrib.admin.views.main import ChangeList
    1212from django.contrib.admin import site, ModelAdmin, SimpleListFilter
     13from django.contrib.admin.filters import RelatedOnlyFieldListFilter
    1314
    1415from models import Book
    1516
     
    6970    list_filter = ('year', 'author', 'contributors', 'is_best_seller', 'date_registered', 'no')
    7071    ordering = ('-id',)
    7172
     73class BookAdminRelatedOnlyFilter(ModelAdmin):
     74    list_filter = ('year', ('author', RelatedOnlyFieldListFilter), ('contributors', RelatedOnlyFieldListFilter),\
     75                   'is_best_seller', 'date_registered', 'no')
     76    ordering = ('-id',)
     77
    7278class DecadeFilterBookAdmin(ModelAdmin):
    7379    list_filter = ('author', DecadeListFilterWithTitleAndParameter)
    7480    ordering = ('-id',)
     
    223229    def test_relatedfieldlistfilter_foreignkey(self):
    224230        modeladmin = BookAdmin(Book, site)
    225231
     232        request = self.request_factory.get('/')
     233        changelist = self.get_changelist(request, Book, modeladmin)
     234
     235        # Make sure that all users are present in the author's list filter
     236        filterspec = changelist.get_filters(request)[0][1]
     237        self.assertEqual(filterspec.lookup_choices, [(1, u'alfred'), (2, u'bob'), (3, u'lisa')])
     238
    226239        request = self.request_factory.get('/', {'author__isnull': 'True'})
    227240        changelist = self.get_changelist(request, Book, modeladmin)
    228241
     
    251264    def test_relatedfieldlistfilter_manytomany(self):
    252265        modeladmin = BookAdmin(Book, site)
    253266
     267        request = self.request_factory.get('/')
     268        changelist = self.get_changelist(request, Book, modeladmin)
     269
     270        # Make sure that all users are present in the contrib's list filter
     271        filterspec = changelist.get_filters(request)[0][2]
     272        self.assertEqual(filterspec.lookup_choices, [(1, u'alfred'), (2, u'bob'), (3, u'lisa')])
     273
    254274        request = self.request_factory.get('/', {'contributors__isnull': 'True'})
    255275        changelist = self.get_changelist(request, Book, modeladmin)
    256276
     
    328348        self.assertEqual(choice['selected'], True)
    329349        self.assertEqual(choice['query_string'], '?books_contributed__id__exact=%d' % self.django_book.pk)
    330350
     351    def test_relatedonlyfieldlistfilter_foreignkey(self):
     352        modeladmin = BookAdminRelatedOnlyFilter(Book, site)
     353
     354        request = self.request_factory.get('/')
     355        changelist = self.get_changelist(request, Book, modeladmin)
     356
     357        # Make sure that only actual authors are present in author's list filter
     358        filterspec = changelist.get_filters(request)[0][1]
     359        self.assertEqual(filterspec.lookup_choices, [(1, u'alfred'), (2, u'bob')])
     360
     361    def test_relatedonlyfieldlistfilter_manytomany(self):
     362        modeladmin = BookAdminRelatedOnlyFilter(Book, site)
     363
     364        request = self.request_factory.get('/')
     365        changelist = self.get_changelist(request, Book, modeladmin)
     366
     367        # Make sure that only actual contributors are present in contrib's list filter
     368        filterspec = changelist.get_filters(request)[0][2]
     369        self.assertEqual(filterspec.lookup_choices, [(2, u'bob'), (3, u'lisa')])
     370
    331371    def test_booleanfieldlistfilter(self):
    332372        modeladmin = BookAdmin(Book, site)
    333373        self.verify_booleanfieldlistfilter(modeladmin)
Back to Top