Code

Ticket #8528: ticket8528-nullfilter-1-1-1-final.diff

File ticket8528-nullfilter-1-1-1-final.diff, 3.7 KB (added by marcob, 4 years ago)
Line 
1Index: django/contrib/admin/filterspecs.py
2===================================================================
3--- django/contrib/admin/filterspecs.py (revision 11627)
4+++ django/contrib/admin/filterspecs.py (working copy)
5@@ -61,7 +61,9 @@
6             self.lookup_title = f.verbose_name
7         rel_name = f.rel.to._meta.pk.name
8         self.lookup_kwarg = '%s__%s__exact' % (self.field_path, rel_name)
9+        self.lookup_null_kwarg = '%s__isnull' % (f.name)
10         self.lookup_val = request.GET.get(self.lookup_kwarg, None)
11+        self.lookup_null = request.GET.get(self.lookup_null_kwarg, None)
12         self.lookup_choices = f.get_choices(include_blank=False)
13 
14     def has_output(self):
15@@ -71,13 +73,17 @@
16         return self.lookup_title
17 
18     def choices(self, cl):
19-        yield {'selected': self.lookup_val is None,
20-               'query_string': cl.get_query_string({}, [self.lookup_kwarg]),
21+        yield {'selected': self.lookup_val is None and not self.lookup_null,
22+               'query_string': cl.get_query_string({}, [self.lookup_kwarg, self.lookup_null_kwarg]),
23                'display': _('All')}
24         for pk_val, val in self.lookup_choices:
25             yield {'selected': self.lookup_val == smart_unicode(pk_val),
26-                   'query_string': cl.get_query_string({self.lookup_kwarg: pk_val}),
27+                   'query_string': cl.get_query_string({self.lookup_kwarg: pk_val}, [self.lookup_null_kwarg]),
28                    'display': val}
29+        if self.field.null:
30+            yield {'selected': self.lookup_null,
31+                   'query_string': cl.get_query_string({self.lookup_null_kwarg: 'True'}, [self.lookup_kwarg]),
32+                   'display': '(%s)' % _("None")}
33 
34 FilterSpec.register(lambda f: bool(f.rel), RelatedFilterSpec)
35 
36@@ -163,19 +169,24 @@
37     def __init__(self, f, request, params, model, model_admin, field_path=None):
38         super(AllValuesFilterSpec, self).__init__(f, request, params, model, model_admin, field_path=field_path)
39         self.lookup_val = request.GET.get(self.field_path, None)
40-        #self.lookup_choices = model_admin.queryset(request).distinct().order_by(f.name).values(f.name)
41+        self.lookup_null = request.GET.get(f.name + '__isnull', None)
42         self.lookup_choices = model._default_manager.all().distinct().order_by(f.name).values(f.name)
43 
44     def title(self):
45         return self.field.verbose_name
46 
47     def choices(self, cl):
48-        yield {'selected': self.lookup_val is None,
49-               'query_string': cl.get_query_string({}, [self.field_path]),
50+        yield {'selected': self.lookup_val is None and not self.lookup_null,
51+               'query_string': cl.get_query_string({}, [self.field.name, self.field_path + '__isnull']),
52                'display': _('All')}
53         for val in self.lookup_choices:
54-            val = smart_unicode(val[self.field.name])
55-            yield {'selected': self.lookup_val == val,
56-                   'query_string': cl.get_query_string({self.field_path: val}),
57-                   'display': val}
58-FilterSpec.register(lambda f: True, AllValuesFilterSpec)
59+            if val[self.field_path] is None:
60+                yield {'selected': self.lookup_null,
61+                       'query_string': cl.get_query_string({self.field_path + '__isnull': 'True'}, [self.field_path]),
62+                       'display': '(%s)' % _("None")}
63+            else:
64+                val = smart_unicode(val[self.field_path])
65+                yield {'selected': self.lookup_val == val,
66+                       'query_string': cl.get_query_string({self.field_path: val}, [self.field_path + '__isnull']),
67+                       'display': val}
68+FilterSpec.register(lambda f: True, AllValuesFilterSpec)