Ticket #15960: 15960.simplelistfilter-queryset-based-lookups.diff
File 15960.simplelistfilter-queryset-based-lookups.diff, 12.8 KB (added by , 14 years ago) |
---|
-
django/contrib/admin/filters.py
diff --git a/django/contrib/admin/filters.py b/django/contrib/admin/filters.py index 36dcea1..22ce36f 100644
a b class SimpleListFilter(ListFilter): 63 63 raise ImproperlyConfigured( 64 64 "The list filter '%s' does not specify " 65 65 "a 'parameter_name'." % self.__class__.__name__) 66 lookup_choices = self.lookups(request )66 lookup_choices = self.lookups(request, model_admin) 67 67 if lookup_choices is None: 68 68 lookup_choices = () 69 69 self.lookup_choices = lookup_choices … … class SimpleListFilter(ListFilter): 78 78 """ 79 79 return self.params.get(self.parameter_name, None) 80 80 81 def lookups(self, request ):81 def lookups(self, request, model_admin): 82 82 """ 83 83 Must be overriden to return a list of tuples (value, verbose value) 84 84 """ -
docs/ref/contrib/admin/index.txt
diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt index e8bc597..6b403ed 100644
a b subclass:: 568 568 # Parameter for the filter that will be used in the URL query. 569 569 parameter_name = 'decade' 570 570 571 def lookups(self, request ):571 def lookups(self, request, model_admin): 572 572 """ 573 573 Returns a list of tuples. The first element in each 574 574 tuple is the coded value for the option that will … … subclass:: 578 578 """ 579 579 return ( 580 580 ('80s', 'in the eighties'), 581 (' other', 'other'),581 ('90s', 'in the nineties'), 582 582 ) 583 583 584 584 def queryset(self, request, queryset): 585 585 """ 586 586 Returns the filtered queryset based on the value 587 587 provided in the query string and retrievable via 588 ` `value()``.588 `self.value()`. 589 589 """ 590 590 # Compare the requested value (either '80s' or 'other') 591 591 # to decide how to filter the queryset. 592 592 if self.value() == '80s': 593 593 return queryset.filter(birthday__year__gte=1980, 594 594 birthday__year__lte=1989) 595 if self.value() == ' other':596 return queryset.filter( Q(year__lte=1979) |597 Q(year__gte=1990))595 if self.value() == '90s': 596 return queryset.filter(birthday__year__gte=1990, 597 birthday__year__lte=1999) 598 598 599 599 class PersonAdmin(ModelAdmin): 600 600 list_filter = (DecadeBornListFilter,) … … subclass:: 602 602 .. note:: 603 603 604 604 As a convenience, the ``HttpRequest`` object is passed to the 605 filter'smethods, for example::605 ``lookups`` and ``queryset`` methods, for example:: 606 606 607 607 class AuthDecadeBornListFilter(DecadeBornListFilter): 608 608 609 def lookups(self, request ):609 def lookups(self, request, model_admin): 610 610 if request.user.is_superuser: 611 return super(AuthDecadeBornListFilter, self).lookups(request) 611 return super(AuthDecadeBornListFilter, self) \ 612 .lookups(request, model_admin) 612 613 613 614 def queryset(self, request, queryset): 614 615 if request.user.is_superuser: 615 return super(AuthDecadeBornListFilter, self).queryset(request, queryset) 616 return super(AuthDecadeBornListFilter, self) \ 617 .queryset(request, queryset) 618 619 Also as a convenience, the ``ModelAdmin`` objects is passed to the 620 ``lookups`` method, for example if you want to base the lookups on the 621 available data:: 622 623 class AnotherDecadeBornListFilter(DecadeBornListFilter): 624 625 def lookups(self, request, model_admin): 626 """ 627 Only show the lookups if there actually is anyone born in 628 the corresponding decades. 629 """ 630 born_in_80s = model_admin.queryset(request) \ 631 .filter(birthday__year__gte=1980, 632 birthday__year__lte=1989) 633 born_in_90s = model_admin.queryset(request) \ 634 .filter(birthday__year__gte=1990, 635 birthday__year__lte=1999) 636 options = tuple() 637 if born_in_80s.count() > 0: 638 options += (('80s', "in the eighties"),) 639 if books_90s.count() > 0: 640 options += (('90s', "in the nineties"),) 641 return options 616 642 617 643 * a tuple, where the first element is a field name and the second 618 644 element is a class inheriting from -
tests/regressiontests/admin_filters/tests.py
diff --git a/tests/regressiontests/admin_filters/tests.py b/tests/regressiontests/admin_filters/tests.py index 6b32475..72776d7 100644
a b def select_by(dictlist, key, value): 19 19 20 20 class DecadeListFilter(SimpleListFilter): 21 21 22 def lookups(self, request ):22 def lookups(self, request, model_admin): 23 23 return ( 24 ('the 80s', "the 1980's"), 24 25 ('the 90s', "the 1990's"), 25 26 ('the 00s', "the 2000's"), 26 27 ('other', "other decades"), … … class DecadeListFilter(SimpleListFilter): 28 29 29 30 def queryset(self, request, queryset): 30 31 decade = self.value() 32 if decade == 'the 80s': 33 return queryset.filter(year__gte=1980, year__lte=1989) 31 34 if decade == 'the 90s': 32 35 return queryset.filter(year__gte=1990, year__lte=1999) 33 36 if decade == 'the 00s': … … class DecadeListFilterWithoutParameter(DecadeListFilter): 45 48 46 49 class DecadeListFilterWithNoneReturningLookups(DecadeListFilterWithTitleAndParameter): 47 50 48 def lookups(self, request ):51 def lookups(self, request, model_admin): 49 52 pass 50 53 54 class DecadeListFilterWithQuerysetBasedLookups(DecadeListFilterWithTitleAndParameter): 55 56 def lookups(self, request, model_admin): 57 books_80s = model_admin.queryset(request).filter(year__gte=1980, year__lte=1989) 58 books_90s = model_admin.queryset(request).filter(year__gte=1990, year__lte=1999) 59 books_00s = model_admin.queryset(request).filter(year__gte=2000, year__lte=2009) 60 options = tuple() 61 if books_80s.count() > 0: 62 options += (('the 80s', "the 1980's"),) 63 if books_90s.count() > 0: 64 options += (('the 90s', "the 1990's"),) 65 if books_00s.count() > 0: 66 options += (('the 00s', "the 2000's"),) 67 return options 68 69 51 70 class CustomUserAdmin(UserAdmin): 52 71 list_filter = ('books_authored', 'books_contributed') 53 72 … … class DecadeFilterBookAdminWithoutParameter(ModelAdmin): 68 87 class DecadeFilterBookAdminWithNoneReturningLookups(ModelAdmin): 69 88 list_filter = (DecadeListFilterWithNoneReturningLookups,) 70 89 90 class DecadeFilterBookAdminWithQuerysetBasedLookups(ModelAdmin): 91 list_filter = (DecadeListFilterWithQuerysetBasedLookups,) 92 71 93 class ListFiltersTests(TestCase): 72 94 73 95 def setUp(self): … … class ListFiltersTests(TestCase): 385 407 self.assertEqual(choices[0]['selected'], True) 386 408 self.assertEqual(choices[0]['query_string'], '?') 387 409 410 # Look for books in the 1980s ---------------------------------------- 411 412 request = self.request_factory.get('/', {'publication-decade': 'the 80s'}) 413 changelist = self.get_changelist(request, Book, modeladmin) 414 415 # Make sure the correct queryset is returned 416 queryset = changelist.get_query_set(request) 417 self.assertEqual(list(queryset), []) 418 419 # Make sure the correct choice is selected 420 filterspec = changelist.get_filters(request)[0][1] 421 self.assertEqual(force_unicode(filterspec.title), u'publication decade') 422 choices = list(filterspec.choices(changelist)) 423 self.assertEqual(choices[1]['display'], u'the 1980\'s') 424 self.assertEqual(choices[1]['selected'], True) 425 self.assertEqual(choices[1]['query_string'], '?publication-decade=the+80s') 426 388 427 # Look for books in the 1990s ---------------------------------------- 389 428 390 429 request = self.request_factory.get('/', {'publication-decade': 'the 90s'}) … … class ListFiltersTests(TestCase): 398 437 filterspec = changelist.get_filters(request)[0][1] 399 438 self.assertEqual(force_unicode(filterspec.title), u'publication decade') 400 439 choices = list(filterspec.choices(changelist)) 401 self.assertEqual(choices[ 1]['display'], u'the 1990\'s')402 self.assertEqual(choices[ 1]['selected'], True)403 self.assertEqual(choices[ 1]['query_string'], '?publication-decade=the+90s')440 self.assertEqual(choices[2]['display'], u'the 1990\'s') 441 self.assertEqual(choices[2]['selected'], True) 442 self.assertEqual(choices[2]['query_string'], '?publication-decade=the+90s') 404 443 405 444 # Look for books in the 2000s ---------------------------------------- 406 445 … … class ListFiltersTests(TestCase): 415 454 filterspec = changelist.get_filters(request)[0][1] 416 455 self.assertEqual(force_unicode(filterspec.title), u'publication decade') 417 456 choices = list(filterspec.choices(changelist)) 418 self.assertEqual(choices[ 2]['display'], u'the 2000\'s')419 self.assertEqual(choices[ 2]['selected'], True)420 self.assertEqual(choices[ 2]['query_string'], '?publication-decade=the+00s')457 self.assertEqual(choices[3]['display'], u'the 2000\'s') 458 self.assertEqual(choices[3]['selected'], True) 459 self.assertEqual(choices[3]['query_string'], '?publication-decade=the+00s') 421 460 422 461 # Combine multiple filters ------------------------------------------- 423 462 … … class ListFiltersTests(TestCase): 432 471 filterspec = changelist.get_filters(request)[0][1] 433 472 self.assertEqual(force_unicode(filterspec.title), u'publication decade') 434 473 choices = list(filterspec.choices(changelist)) 435 self.assertEqual(choices[ 2]['display'], u'the 2000\'s')436 self.assertEqual(choices[ 2]['selected'], True)437 self.assertEqual(choices[ 2]['query_string'], '?publication-decade=the+00s&author__id__exact=%s' % self.alfred.pk)474 self.assertEqual(choices[3]['display'], u'the 2000\'s') 475 self.assertEqual(choices[3]['selected'], True) 476 self.assertEqual(choices[3]['query_string'], '?publication-decade=the+00s&author__id__exact=%s' % self.alfred.pk) 438 477 439 478 filterspec = changelist.get_filters(request)[0][0] 440 479 self.assertEqual(force_unicode(filterspec.title), u'author') … … class ListFiltersTests(TestCase): 472 511 changelist = self.get_changelist(request, Book, modeladmin) 473 512 filterspec = changelist.get_filters(request)[0] 474 513 self.assertEqual(len(filterspec), 0) 514 515 def test_simplelistfilter_with_queryset_based_lookups(self): 516 modeladmin = DecadeFilterBookAdminWithQuerysetBasedLookups(Book, site) 517 request = self.request_factory.get('/', {}) 518 changelist = self.get_changelist(request, Book, modeladmin) 519 520 filterspec = changelist.get_filters(request)[0][0] 521 self.assertEqual(force_unicode(filterspec.title), u'publication decade') 522 choices = list(filterspec.choices(changelist)) 523 self.assertEqual(len(choices), 3) 524 525 self.assertEqual(choices[0]['display'], u'All') 526 self.assertEqual(choices[0]['selected'], True) 527 self.assertEqual(choices[0]['query_string'], '?') 528 529 self.assertEqual(choices[1]['display'], u'the 1990\'s') 530 self.assertEqual(choices[1]['selected'], False) 531 self.assertEqual(choices[1]['query_string'], '?publication-decade=the+90s') 532 533 self.assertEqual(choices[2]['display'], u'the 2000\'s') 534 self.assertEqual(choices[2]['selected'], False) 535 self.assertEqual(choices[2]['query_string'], '?publication-decade=the+00s')