diff options
| author | Jannis Leidel <jannis@leidel.info> | 2011-05-03 10:44:23 +0000 |
|---|---|---|
| committer | Jannis Leidel <jannis@leidel.info> | 2011-05-03 10:44:23 +0000 |
| commit | 18d2f4a81611fa4051ccdcfb9dd443f3a247102e (patch) | |
| tree | 86aafec1f0835166a33b84285de6166b03b7bf30 /tests | |
| parent | a85cd1688b7a4468a4836b892f35480dc16ad331 (diff) | |
Fixed #5833 -- Modified the admin list filters to be easier to customize. Many thanks to Honza Král, Tom X. Tobin, gerdemb, eandre, sciyoshi, bendavis78 and Julien Phalip for working on this.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@16144 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/regressiontests/admin_filters/__init__.py (renamed from tests/regressiontests/admin_filterspecs/__init__.py) | 0 | ||||
| -rw-r--r-- | tests/regressiontests/admin_filters/models.py (renamed from tests/regressiontests/admin_filterspecs/models.py) | 16 | ||||
| -rw-r--r-- | tests/regressiontests/admin_filters/tests.py | 455 | ||||
| -rw-r--r-- | tests/regressiontests/admin_filterspecs/tests.py | 211 | ||||
| -rw-r--r-- | tests/regressiontests/admin_views/models.py | 2 | ||||
| -rw-r--r-- | tests/regressiontests/modeladmin/tests.py | 69 |
6 files changed, 523 insertions, 230 deletions
diff --git a/tests/regressiontests/admin_filterspecs/__init__.py b/tests/regressiontests/admin_filters/__init__.py index e69de29bb2..e69de29bb2 100644 --- a/tests/regressiontests/admin_filterspecs/__init__.py +++ b/tests/regressiontests/admin_filters/__init__.py diff --git a/tests/regressiontests/admin_filterspecs/models.py b/tests/regressiontests/admin_filters/models.py index 5b284c7799..80d54c75a6 100644 --- a/tests/regressiontests/admin_filterspecs/models.py +++ b/tests/regressiontests/admin_filters/models.py @@ -2,22 +2,12 @@ from django.db import models from django.contrib.auth.models import User class Book(models.Model): - title = models.CharField(max_length=25) + title = models.CharField(max_length=50) year = models.PositiveIntegerField(null=True, blank=True) author = models.ForeignKey(User, related_name='books_authored', blank=True, null=True) 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) def __unicode__(self): return self.title - -class BoolTest(models.Model): - NO = False - YES = True - YES_NO_CHOICES = ( - (NO, 'no'), - (YES, 'yes') - ) - completed = models.BooleanField( - default=NO, - choices=YES_NO_CHOICES - ) diff --git a/tests/regressiontests/admin_filters/tests.py b/tests/regressiontests/admin_filters/tests.py new file mode 100644 index 0000000000..b1bd6ded5f --- /dev/null +++ b/tests/regressiontests/admin_filters/tests.py @@ -0,0 +1,455 @@ +from __future__ import with_statement + +import datetime + +from django.core.exceptions import ImproperlyConfigured +from django.test import TestCase, RequestFactory +from django.utils.encoding import force_unicode + +from django.contrib.auth.admin import UserAdmin +from django.contrib.auth.models import User +from django.contrib.admin.views.main import ChangeList +from django.contrib.admin import site, ModelAdmin, SimpleListFilter + +from models import Book + +def select_by(dictlist, key, value): + return [x for x in dictlist if x[key] == value][0] + + +class DecadeListFilter(SimpleListFilter): + + def lookups(self, request): + return ( + ('the 90s', "the 1990's"), + ('the 00s', "the 2000's"), + ('other', "other decades"), + ) + + def queryset(self, request, queryset): + decade = self.value() + if decade == 'the 90s': + return queryset.filter(year__gte=1990, year__lte=1999) + if decade == 'the 00s': + return queryset.filter(year__gte=2000, year__lte=2009) + +class DecadeListFilterWithTitleAndParameter(DecadeListFilter): + title = 'publication decade' + parameter_name = 'publication-decade' + +class DecadeListFilterWithoutTitle(DecadeListFilter): + parameter_name = 'publication-decade' + +class DecadeListFilterWithoutParameter(DecadeListFilter): + title = 'publication decade' + +class CustomUserAdmin(UserAdmin): + list_filter = ('books_authored', 'books_contributed') + +class BookAdmin(ModelAdmin): + list_filter = ('year', 'author', 'contributors', 'is_best_seller', 'date_registered') + order_by = '-id' + +class DecadeFilterBookAdmin(ModelAdmin): + list_filter = ('author', DecadeListFilterWithTitleAndParameter) + order_by = '-id' + +class DecadeFilterBookAdminWithoutTitle(ModelAdmin): + list_filter = (DecadeListFilterWithoutTitle,) + +class DecadeFilterBookAdminWithoutParameter(ModelAdmin): + list_filter = (DecadeListFilterWithoutParameter,) + +class ListFiltersTests(TestCase): + + def setUp(self): + self.today = datetime.date.today() + self.one_week_ago = self.today - datetime.timedelta(days=7) + + self.request_factory = RequestFactory() + + # Users + self.alfred = User.objects.create_user('alfred', 'alfred@example.com') + self.bob = User.objects.create_user('bob', 'bob@example.com') + self.lisa = User.objects.create_user('lisa', 'lisa@example.com') + + # 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.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() + + def get_changelist(self, request, model, modeladmin): + return ChangeList(request, model, modeladmin.list_display, modeladmin.list_display_links, + modeladmin.list_filter, modeladmin.date_hierarchy, modeladmin.search_fields, + modeladmin.list_select_related, modeladmin.list_per_page, modeladmin.list_editable, modeladmin) + + def test_datefieldlistfilter(self): + modeladmin = BookAdmin(Book, site) + + request = self.request_factory.get('/') + changelist = self.get_changelist(request, Book, modeladmin) + + request = self.request_factory.get('/', {'date_registered__year': self.today.year, + 'date_registered__month': self.today.month, + 'date_registered__day': self.today.day}) + 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.django_book, self.djangonaut_book]) + + # Make sure the correct choice is selected + filterspec = changelist.get_filters(request)[0][4] + self.assertEqual(force_unicode(filterspec.title), u'date_registered') + choice = select_by(filterspec.choices(changelist), "display", "Today") + self.assertEqual(choice['selected'], True) + self.assertEqual(choice['query_string'], '?date_registered__day=%s' + '&date_registered__month=%s' + '&date_registered__year=%s' + % (self.today.day, self.today.month, self.today.year)) + + request = self.request_factory.get('/', {'date_registered__year': self.today.year, + 'date_registered__month': self.today.month}) + changelist = self.get_changelist(request, Book, modeladmin) + + # Make sure the correct queryset is returned + queryset = changelist.get_query_set(request) + if (self.today.year, self.today.month) == (self.one_week_ago.year, self.one_week_ago.month): + # In case one week ago is in the same month. + self.assertEqual(list(queryset), [self.gipsy_book, self.django_book, self.djangonaut_book]) + else: + self.assertEqual(list(queryset), [self.django_book, self.djangonaut_book]) + + # Make sure the correct choice is selected + filterspec = changelist.get_filters(request)[0][4] + self.assertEqual(force_unicode(filterspec.title), u'date_registered') + choice = select_by(filterspec.choices(changelist), "display", "This month") + self.assertEqual(choice['selected'], True) + self.assertEqual(choice['query_string'], '?date_registered__month=%s' + '&date_registered__year=%s' + % (self.today.month, self.today.year)) + + request = self.request_factory.get('/', {'date_registered__year': self.today.year}) + changelist = self.get_changelist(request, Book, modeladmin) + + # Make sure the correct queryset is returned + queryset = changelist.get_query_set(request) + if self.today.year == self.one_week_ago.year: + # In case one week ago is in the same year. + self.assertEqual(list(queryset), [self.gipsy_book, self.django_book, self.djangonaut_book]) + else: + self.assertEqual(list(queryset), [self.django_book, self.djangonaut_book]) + + # Make sure the correct choice is selected + filterspec = changelist.get_filters(request)[0][4] + self.assertEqual(force_unicode(filterspec.title), u'date_registered') + choice = select_by(filterspec.choices(changelist), "display", "This year") + self.assertEqual(choice['selected'], True) + self.assertEqual(choice['query_string'], '?date_registered__year=%s' + % (self.today.year)) + + request = self.request_factory.get('/', {'date_registered__gte': self.one_week_ago.strftime('%Y-%m-%d'), + 'date_registered__lte': self.today.strftime('%Y-%m-%d')}) + 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.gipsy_book, self.django_book, self.djangonaut_book]) + + # Make sure the correct choice is selected + filterspec = changelist.get_filters(request)[0][4] + self.assertEqual(force_unicode(filterspec.title), u'date_registered') + choice = select_by(filterspec.choices(changelist), "display", "Past 7 days") + self.assertEqual(choice['selected'], True) + self.assertEqual(choice['query_string'], '?date_registered__gte=%s' + '&date_registered__lte=%s' + % (self.one_week_ago.strftime('%Y-%m-%d'), self.today.strftime('%Y-%m-%d'))) + + def test_allvaluesfieldlistfilter(self): + modeladmin = BookAdmin(Book, site) + + request = self.request_factory.get('/', {'year__isnull': 'True'}) + 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.django_book]) + + # Make sure the last choice is None and is selected + filterspec = changelist.get_filters(request)[0][0] + self.assertEqual(force_unicode(filterspec.title), u'year') + choices = list(filterspec.choices(changelist)) + self.assertEqual(choices[-1]['selected'], True) + self.assertEqual(choices[-1]['query_string'], '?year__isnull=True') + + request = self.request_factory.get('/', {'year': '2002'}) + changelist = self.get_changelist(request, Book, modeladmin) + + # Make sure the correct choice is selected + filterspec = changelist.get_filters(request)[0][0] + self.assertEqual(force_unicode(filterspec.title), u'year') + choices = list(filterspec.choices(changelist)) + self.assertEqual(choices[2]['selected'], True) + self.assertEqual(choices[2]['query_string'], '?year=2002') + + def test_relatedfieldlistfilter_foreignkey(self): + modeladmin = BookAdmin(Book, site) + + request = self.request_factory.get('/', {'author__isnull': 'True'}) + 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.gipsy_book]) + + # Make sure the last choice is None and is selected + filterspec = changelist.get_filters(request)[0][1] + self.assertEqual(force_unicode(filterspec.title), u'author') + choices = list(filterspec.choices(changelist)) + self.assertEqual(choices[-1]['selected'], True) + self.assertEqual(choices[-1]['query_string'], '?author__isnull=True') + + request = self.request_factory.get('/', {'author__id__exact': self.alfred.pk}) + changelist = self.get_changelist(request, Book, modeladmin) + + # Make sure the correct choice is selected + filterspec = changelist.get_filters(request)[0][1] + self.assertEqual(force_unicode(filterspec.title), u'author') + # order of choices depends on User model, which has no order + choice = select_by(filterspec.choices(changelist), "display", "alfred") + self.assertEqual(choice['selected'], True) + self.assertEqual(choice['query_string'], '?author__id__exact=%d' % self.alfred.pk) + + def test_relatedfieldlistfilter_manytomany(self): + modeladmin = BookAdmin(Book, site) + + request = self.request_factory.get('/', {'contributors__isnull': 'True'}) + 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.django_book, self.bio_book, self.djangonaut_book]) + + # Make sure the last choice is None and is selected + filterspec = changelist.get_filters(request)[0][2] + self.assertEqual(force_unicode(filterspec.title), u'user') + choices = list(filterspec.choices(changelist)) + self.assertEqual(choices[-1]['selected'], True) + self.assertEqual(choices[-1]['query_string'], '?contributors__isnull=True') + + request = self.request_factory.get('/', {'contributors__id__exact': self.bob.pk}) + changelist = self.get_changelist(request, Book, modeladmin) + + # Make sure the correct choice is selected + filterspec = changelist.get_filters(request)[0][2] + self.assertEqual(force_unicode(filterspec.title), u'user') + choice = select_by(filterspec.choices(changelist), "display", "bob") + self.assertEqual(choice['selected'], True) + self.assertEqual(choice['query_string'], '?contributors__id__exact=%d' % self.bob.pk) + + def test_relatedfieldlistfilter_reverse_relationships(self): + modeladmin = CustomUserAdmin(User, site) + + # FK relationship ----- + request = self.request_factory.get('/', {'books_authored__isnull': 'True'}) + changelist = self.get_changelist(request, User, modeladmin) + + # Make sure the correct queryset is returned + queryset = changelist.get_query_set(request) + self.assertEqual(list(queryset), [self.lisa]) + + # Make sure the last choice is None and is selected + filterspec = changelist.get_filters(request)[0][0] + self.assertEqual(force_unicode(filterspec.title), u'book') + choices = list(filterspec.choices(changelist)) + self.assertEqual(choices[-1]['selected'], True) + self.assertEqual(choices[-1]['query_string'], '?books_authored__isnull=True') + + request = self.request_factory.get('/', {'books_authored__id__exact': self.bio_book.pk}) + changelist = self.get_changelist(request, User, modeladmin) + + # Make sure the correct choice is selected + filterspec = changelist.get_filters(request)[0][0] + self.assertEqual(force_unicode(filterspec.title), u'book') + choice = select_by(filterspec.choices(changelist), "display", self.bio_book.title) + self.assertEqual(choice['selected'], True) + self.assertEqual(choice['query_string'], '?books_authored__id__exact=%d' % self.bio_book.pk) + + # M2M relationship ----- + request = self.request_factory.get('/', {'books_contributed__isnull': 'True'}) + changelist = self.get_changelist(request, User, modeladmin) + + # Make sure the correct queryset is returned + queryset = changelist.get_query_set(request) + self.assertEqual(list(queryset), [self.alfred]) + + # Make sure the last choice is None and is selected + filterspec = changelist.get_filters(request)[0][1] + self.assertEqual(force_unicode(filterspec.title), u'book') + choices = list(filterspec.choices(changelist)) + self.assertEqual(choices[-1]['selected'], True) + self.assertEqual(choices[-1]['query_string'], '?books_contributed__isnull=True') + + request = self.request_factory.get('/', {'books_contributed__id__exact': self.django_book.pk}) + changelist = self.get_changelist(request, User, modeladmin) + + # Make sure the correct choice is selected + filterspec = changelist.get_filters(request)[0][1] + self.assertEqual(force_unicode(filterspec.title), u'book') + choice = select_by(filterspec.choices(changelist), "display", self.django_book.title) + self.assertEqual(choice['selected'], True) + self.assertEqual(choice['query_string'], '?books_contributed__id__exact=%d' % self.django_book.pk) + + def test_booleanfieldlistfilter(self): + modeladmin = BookAdmin(Book, site) + self.verify_booleanfieldlistfilter(modeladmin) + + def test_booleanfieldlistfilter_tuple(self): + modeladmin = BookAdmin(Book, site) + self.verify_booleanfieldlistfilter(modeladmin) + + def verify_booleanfieldlistfilter(self, modeladmin): + request = self.request_factory.get('/') + changelist = self.get_changelist(request, Book, modeladmin) + + request = self.request_factory.get('/', {'is_best_seller__exact': 0}) + 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]) + + # Make sure the correct choice is selected + filterspec = changelist.get_filters(request)[0][3] + self.assertEqual(force_unicode(filterspec.title), u'is_best_seller') + choice = select_by(filterspec.choices(changelist), "display", "No") + self.assertEqual(choice['selected'], True) + self.assertEqual(choice['query_string'], '?is_best_seller__exact=0') + + request = self.request_factory.get('/', {'is_best_seller__exact': 1}) + 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.gipsy_book, self.djangonaut_book]) + + # Make sure the correct choice is selected + filterspec = changelist.get_filters(request)[0][3] + self.assertEqual(force_unicode(filterspec.title), u'is_best_seller') + choice = select_by(filterspec.choices(changelist), "display", "Yes") + self.assertEqual(choice['selected'], True) + self.assertEqual(choice['query_string'], '?is_best_seller__exact=1') + + request = self.request_factory.get('/', {'is_best_seller__isnull': 'True'}) + 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.django_book]) + + # Make sure the correct choice is selected + filterspec = changelist.get_filters(request)[0][3] + self.assertEqual(force_unicode(filterspec.title), u'is_best_seller') + choice = select_by(filterspec.choices(changelist), "display", "Unknown") + self.assertEqual(choice['selected'], True) + self.assertEqual(choice['query_string'], '?is_best_seller__isnull=True') + + def test_simplelistfilter(self): + modeladmin = DecadeFilterBookAdmin(Book, site) + + # Make sure that the first option is 'All' --------------------------- + + request = self.request_factory.get('/', {}) + changelist = self.get_changelist(request, Book, modeladmin) + + # Make sure the correct queryset is returned + queryset = changelist.get_query_set(request) + self.assertEqual(list(queryset), list(Book.objects.all().order_by('-id'))) + + # Make sure the correct choice is selected + filterspec = changelist.get_filters(request)[0][1] + self.assertEqual(force_unicode(filterspec.title), u'publication decade') + choices = list(filterspec.choices(changelist)) + self.assertEqual(choices[0]['display'], u'All') + self.assertEqual(choices[0]['selected'], True) + self.assertEqual(choices[0]['query_string'], '?') + + # Look for books in the 1990s ---------------------------------------- + + request = self.request_factory.get('/', {'publication-decade': 'the 90s'}) + 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]) + + # Make sure the correct choice is selected + filterspec = changelist.get_filters(request)[0][1] + self.assertEqual(force_unicode(filterspec.title), u'publication decade') + choices = list(filterspec.choices(changelist)) + self.assertEqual(choices[1]['display'], u'the 1990\'s') + self.assertEqual(choices[1]['selected'], True) + self.assertEqual(choices[1]['query_string'], '?publication-decade=the+90s') + + # Look for books in the 2000s ---------------------------------------- + + request = self.request_factory.get('/', {'publication-decade': 'the 00s'}) + 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.gipsy_book, self.djangonaut_book]) + + # Make sure the correct choice is selected + filterspec = changelist.get_filters(request)[0][1] + self.assertEqual(force_unicode(filterspec.title), u'publication decade') + choices = list(filterspec.choices(changelist)) + self.assertEqual(choices[2]['display'], u'the 2000\'s') + self.assertEqual(choices[2]['selected'], True) + self.assertEqual(choices[2]['query_string'], '?publication-decade=the+00s') + + # Combine multiple filters ------------------------------------------- + + request = self.request_factory.get('/', {'publication-decade': 'the 00s', 'author__id__exact': self.alfred.pk}) + 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.djangonaut_book]) + + # Make sure the correct choices are selected + filterspec = changelist.get_filters(request)[0][1] + self.assertEqual(force_unicode(filterspec.title), u'publication decade') + choices = list(filterspec.choices(changelist)) + self.assertEqual(choices[2]['display'], u'the 2000\'s') + self.assertEqual(choices[2]['selected'], True) + self.assertEqual(choices[2]['query_string'], '?publication-decade=the+00s&author__id__exact=%s' % self.alfred.pk) + + filterspec = changelist.get_filters(request)[0][0] + self.assertEqual(force_unicode(filterspec.title), u'author') + choice = select_by(filterspec.choices(changelist), "display", "alfred") + self.assertEqual(choice['selected'], True) + self.assertEqual(choice['query_string'], '?publication-decade=the+00s&author__id__exact=%s' % self.alfred.pk) + + def test_listfilter_without_title(self): + """ + Any filter must define a title. + """ + modeladmin = DecadeFilterBookAdminWithoutTitle(Book, site) + request = self.request_factory.get('/', {}) + self.assertRaisesRegexp(ImproperlyConfigured, + "The list filter 'DecadeListFilterWithoutTitle' does not specify a 'title'.", + self.get_changelist, request, Book, modeladmin) + + def test_simplelistfilter_without_parameter(self): + """ + Any SimpleListFilter must define a parameter_name. + """ + modeladmin = DecadeFilterBookAdminWithoutParameter(Book, site) + request = self.request_factory.get('/', {}) + self.assertRaisesRegexp(ImproperlyConfigured, + "The list filter 'DecadeListFilterWithoutParameter' does not specify a 'parameter_name'.", + self.get_changelist, request, Book, modeladmin) diff --git a/tests/regressiontests/admin_filterspecs/tests.py b/tests/regressiontests/admin_filterspecs/tests.py deleted file mode 100644 index 8b9e734313..0000000000 --- a/tests/regressiontests/admin_filterspecs/tests.py +++ /dev/null @@ -1,211 +0,0 @@ -from django.contrib.auth.admin import UserAdmin -from django.test import TestCase -from django.test.client import RequestFactory -from django.contrib.auth.models import User -from django.contrib import admin -from django.contrib.admin.views.main import ChangeList -from django.utils.encoding import force_unicode - -from models import Book, BoolTest - -def select_by(dictlist, key, value): - return [x for x in dictlist if x[key] == value][0] - -class FilterSpecsTests(TestCase): - - def setUp(self): - # Users - self.alfred = User.objects.create_user('alfred', 'alfred@example.com') - self.bob = User.objects.create_user('bob', 'bob@example.com') - lisa = User.objects.create_user('lisa', 'lisa@example.com') - - #Books - self.bio_book = Book.objects.create(title='Django: a biography', year=1999, author=self.alfred) - self.django_book = Book.objects.create(title='The Django Book', year=None, author=self.bob) - gipsy_book = Book.objects.create(title='Gipsy guitar for dummies', year=2002) - gipsy_book.contributors = [self.bob, lisa] - gipsy_book.save() - - # BoolTests - self.trueTest = BoolTest.objects.create(completed=True) - self.falseTest = BoolTest.objects.create(completed=False) - - self.request_factory = RequestFactory() - - - def get_changelist(self, request, model, modeladmin): - return ChangeList(request, model, modeladmin.list_display, modeladmin.list_display_links, - modeladmin.list_filter, modeladmin.date_hierarchy, modeladmin.search_fields, - modeladmin.list_select_related, modeladmin.list_per_page, modeladmin.list_editable, modeladmin) - - def test_AllValuesFilterSpec(self): - modeladmin = BookAdmin(Book, admin.site) - - request = self.request_factory.get('/', {'year__isnull': 'True'}) - changelist = self.get_changelist(request, Book, modeladmin) - - # Make sure changelist.get_query_set() does not raise IncorrectLookupParameters - queryset = changelist.get_query_set() - - # Make sure the last choice is None and is selected - filterspec = changelist.get_filters(request)[0][0] - self.assertEqual(force_unicode(filterspec.title()), u'year') - choices = list(filterspec.choices(changelist)) - self.assertEqual(choices[-1]['selected'], True) - self.assertEqual(choices[-1]['query_string'], '?year__isnull=True') - - request = self.request_factory.get('/', {'year': '2002'}) - changelist = self.get_changelist(request, Book, modeladmin) - - # Make sure the correct choice is selected - filterspec = changelist.get_filters(request)[0][0] - self.assertEqual(force_unicode(filterspec.title()), u'year') - choices = list(filterspec.choices(changelist)) - self.assertEqual(choices[2]['selected'], True) - self.assertEqual(choices[2]['query_string'], '?year=2002') - - def test_RelatedFilterSpec_ForeignKey(self): - modeladmin = BookAdmin(Book, admin.site) - - request = self.request_factory.get('/', {'author__isnull': 'True'}) - changelist = ChangeList(request, Book, modeladmin.list_display, modeladmin.list_display_links, - modeladmin.list_filter, modeladmin.date_hierarchy, modeladmin.search_fields, - modeladmin.list_select_related, modeladmin.list_per_page, modeladmin.list_editable, modeladmin) - - # Make sure changelist.get_query_set() does not raise IncorrectLookupParameters - queryset = changelist.get_query_set() - - # Make sure the last choice is None and is selected - filterspec = changelist.get_filters(request)[0][1] - self.assertEqual(force_unicode(filterspec.title()), u'author') - choices = list(filterspec.choices(changelist)) - self.assertEqual(choices[-1]['selected'], True) - self.assertEqual(choices[-1]['query_string'], '?author__isnull=True') - - request = self.request_factory.get('/', {'author__id__exact': self.alfred.pk}) - changelist = self.get_changelist(request, Book, modeladmin) - - # Make sure the correct choice is selected - filterspec = changelist.get_filters(request)[0][1] - self.assertEqual(force_unicode(filterspec.title()), u'author') - # order of choices depends on User model, which has no order - choice = select_by(filterspec.choices(changelist), "display", "alfred") - self.assertEqual(choice['selected'], True) - self.assertEqual(choice['query_string'], '?author__id__exact=%d' % self.alfred.pk) - - def test_RelatedFilterSpec_ManyToMany(self): - modeladmin = BookAdmin(Book, admin.site) - - request = self.request_factory.get('/', {'contributors__isnull': 'True'}) - changelist = self.get_changelist(request, Book, modeladmin) - - # Make sure changelist.get_query_set() does not raise IncorrectLookupParameters - queryset = changelist.get_query_set() - - # Make sure the last choice is None and is selected - filterspec = changelist.get_filters(request)[0][2] - self.assertEqual(force_unicode(filterspec.title()), u'user') - choices = list(filterspec.choices(changelist)) - self.assertEqual(choices[-1]['selected'], True) - self.assertEqual(choices[-1]['query_string'], '?contributors__isnull=True') - - request = self.request_factory.get('/', {'contributors__id__exact': self.bob.pk}) - changelist = self.get_changelist(request, Book, modeladmin) - - # Make sure the correct choice is selected - filterspec = changelist.get_filters(request)[0][2] - self.assertEqual(force_unicode(filterspec.title()), u'user') - choice = select_by(filterspec.choices(changelist), "display", "bob") - self.assertEqual(choice['selected'], True) - self.assertEqual(choice['query_string'], '?contributors__id__exact=%d' % self.bob.pk) - - - def test_RelatedFilterSpec_reverse_relationships(self): - modeladmin = CustomUserAdmin(User, admin.site) - - # FK relationship ----- - request = self.request_factory.get('/', {'books_authored__isnull': 'True'}) - changelist = self.get_changelist(request, User, modeladmin) - - # Make sure changelist.get_query_set() does not raise IncorrectLookupParameters - queryset = changelist.get_query_set() - - # Make sure the last choice is None and is selected - filterspec = changelist.get_filters(request)[0][0] - self.assertEqual(force_unicode(filterspec.title()), u'book') - choices = list(filterspec.choices(changelist)) - self.assertEqual(choices[-1]['selected'], True) - self.assertEqual(choices[-1]['query_string'], '?books_authored__isnull=True') - - request = self.request_factory.get('/', {'books_authored__id__exact': self.bio_book.pk}) - changelist = self.get_changelist(request, User, modeladmin) - - # Make sure the correct choice is selected - filterspec = changelist.get_filters(request)[0][0] - self.assertEqual(force_unicode(filterspec.title()), u'book') - choice = select_by(filterspec.choices(changelist), "display", self.bio_book.title) - self.assertEqual(choice['selected'], True) - self.assertEqual(choice['query_string'], '?books_authored__id__exact=%d' % self.bio_book.pk) - - # M2M relationship ----- - request = self.request_factory.get('/', {'books_contributed__isnull': 'True'}) - changelist = self.get_changelist(request, User, modeladmin) - - # Make sure changelist.get_query_set() does not raise IncorrectLookupParameters - queryset = changelist.get_query_set() - - # Make sure the last choice is None and is selected - filterspec = changelist.get_filters(request)[0][1] - self.assertEqual(force_unicode(filterspec.title()), u'book') - choices = list(filterspec.choices(changelist)) - self.assertEqual(choices[-1]['selected'], True) - self.assertEqual(choices[-1]['query_string'], '?books_contributed__isnull=True') - - request = self.request_factory.get('/', {'books_contributed__id__exact': self.django_book.pk}) - changelist = self.get_changelist(request, User, modeladmin) - - # Make sure the correct choice is selected - filterspec = changelist.get_filters(request)[0][1] - self.assertEqual(force_unicode(filterspec.title()), u'book') - choice = select_by(filterspec.choices(changelist), "display", self.django_book.title) - self.assertEqual(choice['selected'], True) - self.assertEqual(choice['query_string'], '?books_contributed__id__exact=%d' % self.django_book.pk) - - def test_BooleanFilterSpec(self): - modeladmin = BoolTestAdmin(BoolTest, admin.site) - - request = self.request_factory.get('/') - changelist = ChangeList(request, BoolTest, modeladmin.list_display, modeladmin.list_display_links, - modeladmin.list_filter, modeladmin.date_hierarchy, modeladmin.search_fields, - modeladmin.list_select_related, modeladmin.list_per_page, modeladmin.list_editable, modeladmin) - - # Make sure changelist.get_query_set() does not raise IncorrectLookupParameters - queryset = changelist.get_query_set() - - # Make sure the last choice is None and is selected - filterspec = changelist.get_filters(request)[0][0] - self.assertEqual(force_unicode(filterspec.title()), u'completed') - choices = list(filterspec.choices(changelist)) - self.assertEqual(choices[-1]['selected'], False) - self.assertEqual(choices[-1]['query_string'], '?completed__exact=0') - - request = self.request_factory.get('/', {'completed__exact': 1}) - changelist = self.get_changelist(request, BoolTest, modeladmin) - - # Make sure the correct choice is selected - filterspec = changelist.get_filters(request)[0][0] - self.assertEqual(force_unicode(filterspec.title()), u'completed') - # order of choices depends on User model, which has no order - choice = select_by(filterspec.choices(changelist), "display", "Yes") - self.assertEqual(choice['selected'], True) - self.assertEqual(choice['query_string'], '?completed__exact=1') - -class CustomUserAdmin(UserAdmin): - list_filter = ('books_authored', 'books_contributed') - -class BookAdmin(admin.ModelAdmin): - list_filter = ('year', 'author', 'contributors') - order_by = '-id' - -class BoolTestAdmin(admin.ModelAdmin): - list_filter = ('completed',) diff --git a/tests/regressiontests/admin_views/models.py b/tests/regressiontests/admin_views/models.py index 97f6708e40..6e34ee1272 100644 --- a/tests/regressiontests/admin_views/models.py +++ b/tests/regressiontests/admin_views/models.py @@ -611,7 +611,7 @@ class Gadget(models.Model): return self.name class CustomChangeList(ChangeList): - def get_query_set(self): + def get_query_set(self, request): return self.root_query_set.filter(pk=9999) # Does not exist class GadgetAdmin(admin.ModelAdmin): diff --git a/tests/regressiontests/modeladmin/tests.py b/tests/regressiontests/modeladmin/tests.py index a20e579026..530b476b7c 100644 --- a/tests/regressiontests/modeladmin/tests.py +++ b/tests/regressiontests/modeladmin/tests.py @@ -2,19 +2,21 @@ from datetime import date from django import forms from django.conf import settings -from django.contrib.admin.options import ModelAdmin, TabularInline, \ - HORIZONTAL, VERTICAL +from django.contrib.admin.options import (ModelAdmin, TabularInline, + HORIZONTAL, VERTICAL) from django.contrib.admin.sites import AdminSite from django.contrib.admin.validation import validate from django.contrib.admin.widgets import AdminDateWidget, AdminRadioSelect +from django.contrib.admin import (SimpleListFilter, + BooleanFieldListFilter) from django.core.exceptions import ImproperlyConfigured from django.forms.models import BaseModelFormSet from django.forms.widgets import Select from django.test import TestCase from django.utils import unittest -from models import Band, Concert, ValidationTestModel, \ - ValidationTestInlineModel +from models import (Band, Concert, ValidationTestModel, + ValidationTestInlineModel) # None of the following tests really depend on the content of the request, @@ -851,8 +853,65 @@ class ValidationTests(unittest.TestCase): ValidationTestModel, ) + class RandomClass(object): + pass + + class ValidationTestModelAdmin(ModelAdmin): + list_filter = (RandomClass,) + + self.assertRaisesRegexp( + ImproperlyConfigured, + "'ValidationTestModelAdmin.list_filter\[0\]' is 'RandomClass' which is not a descendant of ListFilter.", + validate, + ValidationTestModelAdmin, + ValidationTestModel, + ) + + class ValidationTestModelAdmin(ModelAdmin): + list_filter = (('is_active', RandomClass),) + + self.assertRaisesRegexp( + ImproperlyConfigured, + "'ValidationTestModelAdmin.list_filter\[0\]\[1\]' is 'RandomClass' which is not of type FieldListFilter.", + validate, + ValidationTestModelAdmin, + ValidationTestModel, + ) + + class AwesomeFilter(SimpleListFilter): + def get_title(self): + return 'awesomeness' + def get_choices(self, request): + return (('bit', 'A bit awesome'), ('very', 'Very awesome'), ) + def get_query_set(self, cl, qs): + return qs + + class ValidationTestModelAdmin(ModelAdmin): + list_filter = (('is_active', AwesomeFilter),) + + self.assertRaisesRegexp( + ImproperlyConfigured, + "'ValidationTestModelAdmin.list_filter\[0\]\[1\]' is 'AwesomeFilter' which is not of type FieldListFilter.", + validate, + ValidationTestModelAdmin, + ValidationTestModel, + ) + + class ValidationTestModelAdmin(ModelAdmin): + list_filter = (BooleanFieldListFilter,) + + self.assertRaisesRegexp( + ImproperlyConfigured, + "'ValidationTestModelAdmin.list_filter\[0\]' is 'BooleanFieldListFilter' which is of type FieldListFilter but is not associated with a field name.", + validate, + ValidationTestModelAdmin, + ValidationTestModel, + ) + + # Valid declarations below ----------- + class ValidationTestModelAdmin(ModelAdmin): - list_filter = ('is_active',) + list_filter = ('is_active', AwesomeFilter, ('is_active', BooleanFieldListFilter)) validate(ValidationTestModelAdmin, ValidationTestModel) |
