Filtering Django Admin by Null/Is Not Null Filtering Django Admin by Null/Is Not Null python python

Filtering Django Admin by Null/Is Not Null


Since Django 1.4 brings some changes to filters, I thought I save someone the time I just spent modifying the code from Cerin's accepted answer to work with Django 1.4 rc1.

I have a model that has TimeField(null=True) named "started" and I wanted to filter for null and non-null values, so it's prety much the same problem as OP.
So, here is what worked for me...

Defined (actually included) these in admin.py:

from django.contrib.admin.filters import SimpleListFilterclass NullFilterSpec(SimpleListFilter):    title = u''    parameter_name = u''    def lookups(self, request, model_admin):        return (            ('1', _('Has value'), ),            ('0', _('None'), ),        )    def queryset(self, request, queryset):        kwargs = {        '%s'%self.parameter_name : None,        }        if self.value() == '0':            return queryset.filter(**kwargs)        if self.value() == '1':            return queryset.exclude(**kwargs)        return querysetclass StartNullFilterSpec(NullFilterSpec):    title = u'Started'    parameter_name = u'started'

Than just used them in ModelAdmin:

class SomeModelAdmin(admin.ModelAdmin):    list_filter =  (StartNullFilterSpec, )


After Django 3.1 you can use EmptyFieldListFilter:

class MyAdmin(admin.ModelAdmin):    list_filter =  (        ("model_field", admin.EmptyFieldListFilter),    )


I have a simpler version of frnhr's answer, which actually filters on __isnull condition.(Django 1.4+):

from django.contrib.admin import SimpleListFilterclass NullListFilter(SimpleListFilter):    def lookups(self, request, model_admin):        return (            ('1', 'Null', ),            ('0', '!= Null', ),        )    def queryset(self, request, queryset):        if self.value() in ('0', '1'):            kwargs = { '{0}__isnull'.format(self.parameter_name) : self.value() == '1' }            return queryset.filter(**kwargs)        return queryset

Then also:

class StartNullListFilter(NullListFilter):    title = u'Started'    parameter_name = u'started'

and finally:

class SomeModelAdmin(admin.ModelAdmin):    list_filter =  (StartNullListFilter, )

I personally don't like to trash my admin.py with dozens of classes, so I came up with such a helper function:

def null_filter(field, title_=None):    class NullListFieldFilter(NullListFilter):        parameter_name = field        title = title_ or parameter_name    return NullListFieldFilter

Which I can later apply as in:

class OtherModelAdmin(admin.ModelAdmin):    list_filter =  (null_filter('somefield'), null_filter('ugly_field', _('Beautiful Name')), )