Skip to content

Commit

Permalink
Fixed #16080 -- Handle admin list filter items with two characters be…
Browse files Browse the repository at this point in the history
…tter. Thanks, Ales Zoulek and Julien Phalip.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@16274 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information
jezdez committed May 24, 2011
1 parent c0303f5 commit 4a4b6b2
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 14 deletions.
12 changes: 5 additions & 7 deletions django/contrib/admin/validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,18 +73,16 @@ def validate(cls, model):
" associated with a field name."
% (cls.__name__, idx, item.__name__))
else:
try:
# Check for option #2 (tuple)
field, list_filter_class = item
except (TypeError, ValueError):
# item is option #1
field = item
else:
if isinstance(item, (tuple, list)):
# item is option #2
field, list_filter_class = item
if not issubclass(list_filter_class, FieldListFilter):
raise ImproperlyConfigured("'%s.list_filter[%d][1]'"
" is '%s' which is not of type FieldListFilter."
% (cls.__name__, idx, list_filter_class.__name__))
else:
# item is option #1
field = item
# Validate the field string
try:
get_fields_from_path(model, field)
Expand Down
6 changes: 3 additions & 3 deletions django/contrib/admin/views/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,10 @@ def get_filters(self, request, use_distinct=False):
self.model, self.model_admin)
else:
field_path = None
try:
# This is custom FieldListFilter class for a given field.
if isinstance(list_filer, (tuple, list)):
# This is a custom FieldListFilter class for a given field.
field, field_list_filter_class = list_filer
except (TypeError, ValueError):
else:
# This is simply a field name, so use the default
# FieldListFilter class that has been registered for
# the type of the given field.
Expand Down
1 change: 1 addition & 0 deletions tests/regressiontests/admin_filters/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class Book(models.Model):
contributors = models.ManyToManyField(User, related_name='books_contributed', blank=True, null=True)
is_best_seller = models.NullBooleanField(default=0)
date_registered = models.DateField(null=True)
no = models.IntegerField(verbose_name=u'number', blank=True, null=True) # This field is intentionally 2 characters long. See #16080.

def __unicode__(self):
return self.title
25 changes: 22 additions & 3 deletions tests/regressiontests/admin_filters/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class CustomUserAdmin(UserAdmin):
list_filter = ('books_authored', 'books_contributed')

class BookAdmin(ModelAdmin):
list_filter = ('year', 'author', 'contributors', 'is_best_seller', 'date_registered')
list_filter = ('year', 'author', 'contributors', 'is_best_seller', 'date_registered', 'no')
order_by = '-id'

class DecadeFilterBookAdmin(ModelAdmin):
Expand Down Expand Up @@ -100,8 +100,8 @@ def setUp(self):

# Books
self.djangonaut_book = Book.objects.create(title='Djangonaut: an art of living', year=2009, author=self.alfred, is_best_seller=True, date_registered=self.today)
self.bio_book = Book.objects.create(title='Django: a biography', year=1999, author=self.alfred, is_best_seller=False)
self.django_book = Book.objects.create(title='The Django Book', year=None, author=self.bob, is_best_seller=None, date_registered=self.today)
self.bio_book = Book.objects.create(title='Django: a biography', year=1999, author=self.alfred, is_best_seller=False, no=207)
self.django_book = Book.objects.create(title='The Django Book', year=None, author=self.bob, is_best_seller=None, date_registered=self.today, no=103)
self.gipsy_book = Book.objects.create(title='Gipsy guitar for dummies', year=2002, is_best_seller=True, date_registered=self.one_week_ago)
self.gipsy_book.contributors = [self.bob, self.lisa]
self.gipsy_book.save()
Expand Down Expand Up @@ -528,3 +528,22 @@ def test_simplelistfilter_with_queryset_based_lookups(self):
self.assertEqual(choices[2]['display'], u'the 2000\'s')
self.assertEqual(choices[2]['selected'], False)
self.assertEqual(choices[2]['query_string'], '?publication-decade=the+00s')

def test_two_characters_long_field(self):
"""
Ensure that list_filter works with two-characters long field names.
Refs #16080.
"""
modeladmin = BookAdmin(Book, site)
request = self.request_factory.get('/', {'no': '207'})
changelist = self.get_changelist(request, Book, modeladmin)

# Make sure the correct queryset is returned
queryset = changelist.get_query_set(request)
self.assertEqual(list(queryset), [self.bio_book])

filterspec = changelist.get_filters(request)[0][-1]
self.assertEqual(force_unicode(filterspec.title), u'number')
choices = list(filterspec.choices(changelist))
self.assertEqual(choices[2]['selected'], True)
self.assertEqual(choices[2]['query_string'], '?no=207')
1 change: 1 addition & 0 deletions tests/regressiontests/modeladmin/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class ValidationTestModel(models.Model):
is_active = models.BooleanField()
pub_date = models.DateTimeField()
band = models.ForeignKey(Band)
no = models.IntegerField(verbose_name="Number", blank=True, null=True) # This field is intentionally 2 characters long. See #16080.

def decade_published_in(self):
return self.pub_date.strftime('%Y')[:3] + "0's"
Expand Down
2 changes: 1 addition & 1 deletion tests/regressiontests/modeladmin/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -911,7 +911,7 @@ class ValidationTestModelAdmin(ModelAdmin):
# Valid declarations below -----------

class ValidationTestModelAdmin(ModelAdmin):
list_filter = ('is_active', AwesomeFilter, ('is_active', BooleanFieldListFilter))
list_filter = ('is_active', AwesomeFilter, ('is_active', BooleanFieldListFilter), 'no')

validate(ValidationTestModelAdmin, ValidationTestModel)

Expand Down

0 comments on commit 4a4b6b2

Please sign in to comment.