Ticket #14467: AllValuesFilterSpec_Null.3.diff

File AllValuesFilterSpec_Null.3.diff, 5.2 KB (added by Anssi Kääriäinen, 14 years ago)

Small refactoring of .2.diff, now without test_sqlite changes!

  • django/contrib/admin/filterspecs.py

    diff --git a/django/contrib/admin/filterspecs.py b/django/contrib/admin/filterspecs.py
    index 6f643ee..39fd3b5 100644
    a b FilterSpec.register(lambda f: isinstance(f, models.BooleanField) or isinstance(f  
    161161class AllValuesFilterSpec(FilterSpec):
    162162    def __init__(self, f, request, params, model, model_admin):
    163163        super(AllValuesFilterSpec, self).__init__(f, request, params, model, model_admin)
    164         self.lookup_val = request.GET.get(f.name, None)
     164        self.lookup_kwarg = f.name
     165        self.lookup_kwarg_isnull = '%s__isnull' % f.name
     166        self.lookup_val = request.GET.get(self.lookup_kwarg, None)
     167        self.lookup_val_isnull = request.GET.get(self.lookup_kwarg_isnull, None)
    165168        self.lookup_choices = model_admin.queryset(request).distinct().order_by(f.name).values(f.name)
    166169
    167170    def title(self):
    168171        return self.field.verbose_name
    169172
    170173    def choices(self, cl):
    171         yield {'selected': self.lookup_val is None,
    172                'query_string': cl.get_query_string({}, [self.field.name]),
     174        # Turn the choices into a list. If changing self.lookup_choices query
     175        # to values_list(f.name, flat=True) is not considered backwards
     176        # incompatible, that is of course the proper solution...
     177        lookup_choice_vals = [val[self.field.name] for val in self.lookup_choices]
     178        yield {'selected': self.lookup_val is None and self.lookup_val_isnull is None,
     179               'query_string': cl.get_query_string({}, [self.lookup_kwarg, self.lookup_kwarg_isnull]),
    173180               'display': _('All')}
    174         for val in self.lookup_choices:
    175             val = smart_unicode(val[self.field.name])
     181
     182        for val in lookup_choice_vals:
     183            if val is None:
     184                continue
     185            val = smart_unicode(val)
    176186            yield {'selected': self.lookup_val == val,
    177                    'query_string': cl.get_query_string({self.field.name: val}),
     187                   'query_string': cl.get_query_string({self.lookup_kwarg: val}, [self.lookup_kwarg_isnull]),
    178188                   'display': val}
     189        if None in lookup_choice_vals:
     190            yield {'selected': self.lookup_val_isnull is not None,
     191                    'query_string': cl.get_query_string({self.lookup_kwarg_isnull: 'True'}, [self.lookup_kwarg]),
     192                    'display': _('None')}
     193
    179194FilterSpec.register(lambda f: True, AllValuesFilterSpec)
  • new file tests/regressiontests/admin_filterspecs/models.py

    diff --git a/tests/regressiontests/admin_filterspecs/__init__.py b/tests/regressiontests/admin_filterspecs/__init__.py
    new file mode 100644
    index 0000000..e69de29
    diff --git a/tests/regressiontests/admin_filterspecs/models.py b/tests/regressiontests/admin_filterspecs/models.py
    new file mode 100644
    index 0000000..00301a7
    - +  
     1from django.db import models
     2
     3class OptionalAge(models.Model):
     4    name = models.CharField(max_length=25)
     5    age = models.PositiveIntegerField(null=True, blank=True)
  • new file tests/regressiontests/admin_filterspecs/tests.py

    diff --git a/tests/regressiontests/admin_filterspecs/tests.py b/tests/regressiontests/admin_filterspecs/tests.py
    new file mode 100644
    index 0000000..3aaf790
    - +  
     1from django.test import TestCase
     2
     3from django.contrib import admin
     4from django.contrib.admin.views.main import ChangeList
     5from django.contrib.admin.options import IncorrectLookupParameters
     6
     7from models import OptionalAge
     8
     9class AllValuesFilterSpecTest(TestCase):
     10    def setUp(self):
     11        OptionalAge.objects.create(name='Sam', age=35)
     12        OptionalAge.objects.create(name='Tilk', age=135)
     13        OptionalAge.objects.create(name='Oneill', age=None)
     14
     15    def testAllValuesFilterSpecTest(self):
     16        m = OptionalAgeAdmin(OptionalAge, admin.site)
     17        r = MockRequest()
     18        r.GET = {'age__isnull': 'True'}
     19        cl = ChangeList(r, OptionalAge, m.list_display, m.list_display_links,
     20            m.list_filter, m.date_hierarchy, m.search_fields,
     21            m.list_select_related, m.list_per_page, m.list_editable, m)
     22        """ make sure cl.get_query_set does not raise IncorrectLookupParameters """
     23        queryset = cl.get_query_set()
     24
     25        """ make sure the last choice is None and is selected """
     26        filterspec = cl.get_filters(r)[0][0]
     27        choices = list(filterspec.choices(cl))
     28        self.assertEquals(choices[3]['selected'], True)
     29        self.assertEquals(choices[3]['query_string'], '?age__isnull=True')
     30
     31        """ make sure correct choice is selected """
     32        r = MockRequest()
     33        r.GET = {'age': '135'}
     34        cl = ChangeList(r, OptionalAge, m.list_display, m.list_display_links,
     35            m.list_filter, m.date_hierarchy, m.search_fields,
     36            m.list_select_related, m.list_per_page, m.list_editable, m)
     37        filterspec = cl.get_filters(r)[0][0]
     38        choices = list(filterspec.choices(cl))
     39        self.assertEquals(choices[2]['selected'], True)
     40        self.assertEquals(choices[2]['query_string'], '?age=135')
     41
     42    def tearDown(self):
     43        OptionalAge.objects.all().delete()
     44
     45class OptionalAgeAdmin(admin.ModelAdmin):
     46    list_filter = ('age',)
     47    order_by = '-id'
     48
     49class MockRequest(object):
     50    GET = {}
Back to Top