Fixed #31636 -- Made BooleanFieldListFilter respect Field.choices.

This commit is contained in:
manav014 2020-09-13 18:13:21 -07:00 committed by Mariusz Felisiak
parent fed257ddff
commit 580a4341cb
3 changed files with 75 additions and 10 deletions

View File

@ -244,10 +244,12 @@ class BooleanFieldListFilter(FieldListFilter):
return [self.lookup_kwarg, self.lookup_kwarg2] return [self.lookup_kwarg, self.lookup_kwarg2]
def choices(self, changelist): def choices(self, changelist):
field_choices = dict(self.field.flatchoices)
for lookup, title in ( for lookup, title in (
(None, _('All')), (None, _('All')),
('1', _('Yes')), ('1', field_choices.get(True, _('Yes'))),
('0', _('No'))): ('0', field_choices.get(False, _('No'))),
):
yield { yield {
'selected': self.lookup_val == lookup and not self.lookup_val2, 'selected': self.lookup_val == lookup and not self.lookup_val2,
'query_string': changelist.get_query_string({self.lookup_kwarg: lookup}, [self.lookup_kwarg2]), 'query_string': changelist.get_query_string({self.lookup_kwarg: lookup}, [self.lookup_kwarg2]),
@ -257,7 +259,7 @@ class BooleanFieldListFilter(FieldListFilter):
yield { yield {
'selected': self.lookup_val2 == 'True', 'selected': self.lookup_val2 == 'True',
'query_string': changelist.get_query_string({self.lookup_kwarg2: 'True'}, [self.lookup_kwarg]), 'query_string': changelist.get_query_string({self.lookup_kwarg2: 'True'}, [self.lookup_kwarg]),
'display': _('Unknown'), 'display': field_choices.get(None, _('Unknown')),
} }

View File

@ -31,6 +31,11 @@ class Book(models.Model):
is_best_seller = models.BooleanField(default=0, null=True) is_best_seller = models.BooleanField(default=0, null=True)
is_best_seller2 = models.NullBooleanField(default=0) is_best_seller2 = models.NullBooleanField(default=0)
date_registered = models.DateField(null=True) date_registered = models.DateField(null=True)
availability = models.BooleanField(choices=(
(False, 'Paid'),
(True, 'Free'),
(None, 'Obscure'),
), null=True)
# This field name is intentionally 2 characters long (#16080). # This field name is intentionally 2 characters long (#16080).
no = models.IntegerField(verbose_name='number', blank=True, null=True) no = models.IntegerField(verbose_name='number', blank=True, null=True)

View File

@ -140,7 +140,7 @@ class CustomUserAdmin(UserAdmin):
class BookAdmin(ModelAdmin): class BookAdmin(ModelAdmin):
list_filter = ('year', 'author', 'contributors', 'is_best_seller', 'date_registered', 'no') list_filter = ('year', 'author', 'contributors', 'is_best_seller', 'date_registered', 'no', 'availability')
ordering = ('-id',) ordering = ('-id',)
@ -156,6 +156,7 @@ class BookAdminWithTupleBooleanFilter(BookAdmin):
('is_best_seller', BooleanFieldListFilter), ('is_best_seller', BooleanFieldListFilter),
'date_registered', 'date_registered',
'no', 'no',
('availability', BooleanFieldListFilter),
) )
@ -288,22 +289,22 @@ class ListFiltersTests(TestCase):
cls.djangonaut_book = Book.objects.create( cls.djangonaut_book = Book.objects.create(
title='Djangonaut: an art of living', year=2009, title='Djangonaut: an art of living', year=2009,
author=cls.alfred, is_best_seller=True, date_registered=cls.today, author=cls.alfred, is_best_seller=True, date_registered=cls.today,
is_best_seller2=True, is_best_seller2=True, availability=True,
) )
cls.bio_book = Book.objects.create( cls.bio_book = Book.objects.create(
title='Django: a biography', year=1999, author=cls.alfred, title='Django: a biography', year=1999, author=cls.alfred,
is_best_seller=False, no=207, is_best_seller=False, no=207,
is_best_seller2=False, is_best_seller2=False, availability=False,
) )
cls.django_book = Book.objects.create( cls.django_book = Book.objects.create(
title='The Django Book', year=None, author=cls.bob, title='The Django Book', year=None, author=cls.bob,
is_best_seller=None, date_registered=cls.today, no=103, is_best_seller=None, date_registered=cls.today, no=103,
is_best_seller2=None, is_best_seller2=None, availability=True,
) )
cls.guitar_book = Book.objects.create( cls.guitar_book = Book.objects.create(
title='Guitar for dummies', year=2002, is_best_seller=True, title='Guitar for dummies', year=2002, is_best_seller=True,
date_registered=cls.one_week_ago, date_registered=cls.one_week_ago,
is_best_seller2=True, is_best_seller2=True, availability=None,
) )
cls.guitar_book.contributors.set([cls.bob, cls.lisa]) cls.guitar_book.contributors.set([cls.bob, cls.lisa])
@ -956,6 +957,63 @@ class ListFiltersTests(TestCase):
self.assertIs(choice['selected'], True) self.assertIs(choice['selected'], True)
self.assertEqual(choice['query_string'], '?is_best_seller__isnull=True') self.assertEqual(choice['query_string'], '?is_best_seller__isnull=True')
def test_booleanfieldlistfilter_choices(self):
modeladmin = BookAdmin(Book, site)
self.verify_booleanfieldlistfilter_choices(modeladmin)
def test_booleanfieldlistfilter_tuple_choices(self):
modeladmin = BookAdminWithTupleBooleanFilter(Book, site)
self.verify_booleanfieldlistfilter_choices(modeladmin)
def verify_booleanfieldlistfilter_choices(self, modeladmin):
# False.
request = self.request_factory.get('/', {'availability__exact': 0})
request.user = self.alfred
changelist = modeladmin.get_changelist_instance(request)
queryset = changelist.get_queryset(request)
self.assertEqual(list(queryset), [self.bio_book])
filterspec = changelist.get_filters(request)[0][6]
self.assertEqual(filterspec.title, 'availability')
choice = select_by(filterspec.choices(changelist), 'display', 'Paid')
self.assertIs(choice['selected'], True)
self.assertEqual(choice['query_string'], '?availability__exact=0')
# True.
request = self.request_factory.get('/', {'availability__exact': 1})
request.user = self.alfred
changelist = modeladmin.get_changelist_instance(request)
queryset = changelist.get_queryset(request)
self.assertEqual(list(queryset), [self.django_book, self.djangonaut_book])
filterspec = changelist.get_filters(request)[0][6]
self.assertEqual(filterspec.title, 'availability')
choice = select_by(filterspec.choices(changelist), 'display', 'Free')
self.assertIs(choice['selected'], True)
self.assertEqual(choice['query_string'], '?availability__exact=1')
# None.
request = self.request_factory.get('/', {'availability__isnull': 'True'})
request.user = self.alfred
changelist = modeladmin.get_changelist_instance(request)
queryset = changelist.get_queryset(request)
self.assertEqual(list(queryset), [self.guitar_book])
filterspec = changelist.get_filters(request)[0][6]
self.assertEqual(filterspec.title, 'availability')
choice = select_by(filterspec.choices(changelist), 'display', 'Obscure')
self.assertIs(choice['selected'], True)
self.assertEqual(choice['query_string'], '?availability__isnull=True')
# All.
request = self.request_factory.get('/')
request.user = self.alfred
changelist = modeladmin.get_changelist_instance(request)
queryset = changelist.get_queryset(request)
self.assertEqual(
list(queryset),
[self.guitar_book, self.django_book, self.bio_book, self.djangonaut_book],
)
filterspec = changelist.get_filters(request)[0][6]
self.assertEqual(filterspec.title, 'availability')
choice = select_by(filterspec.choices(changelist), 'display', 'All')
self.assertIs(choice['selected'], True)
self.assertEqual(choice['query_string'], '?')
def test_booleanfieldlistfilter_nullbooleanfield(self): def test_booleanfieldlistfilter_nullbooleanfield(self):
modeladmin = BookAdmin2(Book, site) modeladmin = BookAdmin2(Book, site)
@ -1212,7 +1270,7 @@ class ListFiltersTests(TestCase):
queryset = changelist.get_queryset(request) queryset = changelist.get_queryset(request)
self.assertEqual(list(queryset), [self.bio_book]) self.assertEqual(list(queryset), [self.bio_book])
filterspec = changelist.get_filters(request)[0][-1] filterspec = changelist.get_filters(request)[0][5]
self.assertEqual(filterspec.title, 'number') self.assertEqual(filterspec.title, 'number')
choices = list(filterspec.choices(changelist)) choices = list(filterspec.choices(changelist))
self.assertIs(choices[2]['selected'], True) self.assertIs(choices[2]['selected'], True)