|
@@ -269,25 +269,43 @@ FieldListFilter.register(
|
|
|
class ChoicesFieldListFilter(FieldListFilter):
|
|
|
def __init__(self, field, request, params, model, model_admin, field_path):
|
|
|
self.lookup_kwarg = '%s__exact' % field_path
|
|
|
+ self.lookup_kwarg_isnull = '%s__isnull' % field_path
|
|
|
self.lookup_val = request.GET.get(self.lookup_kwarg)
|
|
|
+ self.lookup_val_isnull = request.GET.get(self.lookup_kwarg_isnull)
|
|
|
super(ChoicesFieldListFilter, self).__init__(
|
|
|
field, request, params, model, model_admin, field_path)
|
|
|
|
|
|
def expected_parameters(self):
|
|
|
- return [self.lookup_kwarg]
|
|
|
+ return [self.lookup_kwarg, self.lookup_kwarg_isnull]
|
|
|
|
|
|
def choices(self, changelist):
|
|
|
yield {
|
|
|
'selected': self.lookup_val is None,
|
|
|
- 'query_string': changelist.get_query_string({}, [self.lookup_kwarg]),
|
|
|
+ 'query_string': changelist.get_query_string(
|
|
|
+ {}, [self.lookup_kwarg, self.lookup_kwarg_isnull]
|
|
|
+ ),
|
|
|
'display': _('All')
|
|
|
}
|
|
|
+ none_title = ''
|
|
|
for lookup, title in self.field.flatchoices:
|
|
|
+ if lookup is None:
|
|
|
+ none_title = title
|
|
|
+ continue
|
|
|
yield {
|
|
|
'selected': smart_text(lookup) == self.lookup_val,
|
|
|
- 'query_string': changelist.get_query_string({self.lookup_kwarg: lookup}),
|
|
|
+ 'query_string': changelist.get_query_string(
|
|
|
+ {self.lookup_kwarg: lookup}, [self.lookup_kwarg_isnull]
|
|
|
+ ),
|
|
|
'display': title,
|
|
|
}
|
|
|
+ if none_title:
|
|
|
+ yield {
|
|
|
+ 'selected': bool(self.lookup_val_isnull),
|
|
|
+ 'query_string': changelist.get_query_string({
|
|
|
+ self.lookup_kwarg_isnull: 'True',
|
|
|
+ }, [self.lookup_kwarg]),
|
|
|
+ 'display': none_title,
|
|
|
+ }
|
|
|
|
|
|
FieldListFilter.register(lambda f: bool(f.choices), ChoicesFieldListFilter)
|
|
|
|