Django admin list_filter - filter field by is empty (None or empty string "")
Based on MaxCore's answer, I created customised class that I can use to modify title and parameter name:
from django.contrib import admin
from django.utils.translation import ugettext_lazy as _
from django.db.models import Q
class NotNullFilter(admin.SimpleListFilter):
title = _('Filter title not set')
parameter_name = 'parameter name not set'
def lookups(self, request, model_admin):
return (
('not_null', _('Not empty only')),
('null', _('Empty only')),
)
def queryset(self, request, queryset):
if self.value() == 'not_null':
is_null_false = {
self.parameter_name + "__isnull": False
}
exclude = {
self.parameter_name: ""
}
return queryset.filter(**is_null_false).exclude(**exclude)
if self.value() == 'null':
is_null_true = {
self.parameter_name + "__isnull": True
}
param_exact = {
self.parameter_name + "__exact": ""
}
return queryset.filter(Q(**is_null_true) | Q(**param_exact))
class YoutubeNotNullFilter(NotNullFilter):
title = "Youtube"
parameter_name = "youtube_videoid"
As of Django 3.1, you can use EmptyFieldListFilter
as follows:
list_filter = (
("my_fk_field", admin.EmptyFieldListFilter),
)
See the docs for details. See the release notes as well.
The code is available here, if you need to customize it or backport it.
admin.py
class ImageListFilter(admin.SimpleListFilter):
title = _('Has photo')
parameter_name = 'has_photo'
def lookups(self, request, model_admin):
return (
('yes', _('Yes')),
('no', _('No')),
)
def queryset(self, request, queryset):
if self.value() == 'yes':
return queryset.filter(image__isnull=False).exclude(image='')
if self.value() == 'no':
return queryset.filter(Q(image__isnull=True) | Q(image__exact=''))
class UserAdmin(admin.ModelAdmin):
list_filter = [ImageListFilter]