Skip to content

Commit 88e1715

Browse files
sebasmagrijphalip
authored andcommitted
Fixed django#19318 -- Ensured that the admin's SimpleListFilter options can be displayed as selected even if the lookup's first element is not a string.
1 parent 5fa5621 commit 88e1715

File tree

2 files changed

+53
-9
lines changed

2 files changed

+53
-9
lines changed

django/contrib/admin/filters.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
from django.db import models
1111
from django.core.exceptions import ImproperlyConfigured, ValidationError
12-
from django.utils.encoding import smart_text
12+
from django.utils.encoding import smart_text, force_text
1313
from django.utils.translation import ugettext_lazy as _
1414
from django.utils import timezone
1515
from django.contrib.admin.util import (get_model_from_relation,
@@ -102,7 +102,7 @@ def choices(self, cl):
102102
}
103103
for lookup, title in self.lookup_choices:
104104
yield {
105-
'selected': self.value() == lookup,
105+
'selected': self.value() == force_text(lookup),
106106
'query_string': cl.get_query_string({
107107
self.parameter_name: lookup,
108108
}, []),

tests/regressiontests/admin_filters/tests.py

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,21 @@ class DecadeListFilterParameterEndsWith__Isnull(DecadeListFilter):
7878
parameter_name = 'decade__isnull' # Ends with '__isnull"
7979

8080

81+
class DepartmentListFilterLookupWithNonStringValue(SimpleListFilter):
82+
title = 'department'
83+
parameter_name = 'department'
84+
85+
def lookups(self, request, model_admin):
86+
return set([
87+
(employee.department.id, # Intentionally not a string (Refs #19318)
88+
employee.department.code)
89+
for employee in model_admin.queryset(request).all()
90+
])
91+
92+
def queryset(self, request, queryset):
93+
if self.value():
94+
return queryset.filter(department__id=self.value())
95+
8196
class CustomUserAdmin(UserAdmin):
8297
list_filter = ('books_authored', 'books_contributed')
8398

@@ -118,6 +133,10 @@ class EmployeeAdmin(ModelAdmin):
118133
list_filter = ['department']
119134

120135

136+
class DepartmentFilterEmployeeAdmin(EmployeeAdmin):
137+
list_filter = [DepartmentListFilterLookupWithNonStringValue, ]
138+
139+
121140
class ListFiltersTests(TestCase):
122141

123142
def setUp(self):
@@ -140,6 +159,14 @@ def setUp(self):
140159
self.gipsy_book.contributors = [self.bob, self.lisa]
141160
self.gipsy_book.save()
142161

162+
# Departments
163+
self.dev = Department.objects.create(code='DEV', description='Development')
164+
self.design = Department.objects.create(code='DSN', description='Design')
165+
166+
# Employees
167+
self.john = Employee.objects.create(name='John Blue', department=self.dev)
168+
self.jack = Employee.objects.create(name='Jack Red', department=self.design)
169+
143170
def get_changelist(self, request, model, modeladmin):
144171
return ChangeList(request, model, modeladmin.list_display, modeladmin.list_display_links,
145172
modeladmin.list_filter, modeladmin.date_hierarchy, modeladmin.search_fields,
@@ -638,24 +665,41 @@ def test_parameter_ends_with__in__or__isnull(self):
638665
self.assertEqual(choices[2]['selected'], True)
639666
self.assertEqual(choices[2]['query_string'], '?decade__isnull=the+90s')
640667

668+
def test_lookup_with_non_string_value(self):
669+
"""
670+
Ensure choices are set the selected class when using non-string values
671+
for lookups in SimpleListFilters.
672+
Refs #19318
673+
"""
674+
675+
modeladmin = DepartmentFilterEmployeeAdmin(Employee, site)
676+
request = self.request_factory.get('/', {'department': '1'})
677+
changelist = self.get_changelist(request, Employee, modeladmin)
678+
679+
queryset = changelist.get_query_set(request)
680+
681+
self.assertEqual(list(queryset), [self.john])
682+
683+
filterspec = changelist.get_filters(request)[0][-1]
684+
self.assertEqual(force_text(filterspec.title), 'department')
685+
choices = list(filterspec.choices(changelist))
686+
self.assertEqual(choices[2]['display'], 'DEV')
687+
self.assertEqual(choices[2]['selected'], True)
688+
self.assertEqual(choices[2]['query_string'], '?department=1')
689+
641690
def test_fk_with_to_field(self):
642691
"""
643692
Ensure that a filter on a FK respects the FK's to_field attribute.
644693
Refs #17972.
645694
"""
646695
modeladmin = EmployeeAdmin(Employee, site)
647696

648-
dev = Department.objects.create(code='DEV', description='Development')
649-
design = Department.objects.create(code='DSN', description='Design')
650-
john = Employee.objects.create(name='John Blue', department=dev)
651-
jack = Employee.objects.create(name='Jack Red', department=design)
652-
653697
request = self.request_factory.get('/', {})
654698
changelist = self.get_changelist(request, Employee, modeladmin)
655699

656700
# Make sure the correct queryset is returned
657701
queryset = changelist.get_query_set(request)
658-
self.assertEqual(list(queryset), [jack, john])
702+
self.assertEqual(list(queryset), [self.jack, self.john])
659703

660704
filterspec = changelist.get_filters(request)[0][-1]
661705
self.assertEqual(force_text(filterspec.title), 'department')
@@ -680,7 +724,7 @@ def test_fk_with_to_field(self):
680724

681725
# Make sure the correct queryset is returned
682726
queryset = changelist.get_query_set(request)
683-
self.assertEqual(list(queryset), [john])
727+
self.assertEqual(list(queryset), [self.john])
684728

685729
filterspec = changelist.get_filters(request)[0][-1]
686730
self.assertEqual(force_text(filterspec.title), 'department')

0 commit comments

Comments
 (0)