I have a simple Django model like:
class Person(models.Model):
referrer = models.ForeignKey('self', null=True)
...
In this model's ModelAdmin, how would I allow it to be filtered by whether or not referrer is null? By default, adding referrer to list_filter causes a dropdown to be shown that lists every person record, which may be in the hundreds of thousands, effectively preventing the page from loading. Even if it loads, I still can't filter by the criteria I want.
i.e. How would I modify this so that the dropdown only lists "All", "Null", or "Not Null" choices?
I've seen some posts that claim to accomplish something similar using custom FilterSpec subclasses, but none of them explain how to use them. The few I've seen appear to apply to all fields in all models, which I wouldn't want. Moreover, there's zero documentation for FilterSpec, which makes me nervous, because I don't want to invest in a lot of custom code tied to some transient internal class that might disappear by the next release.
null=True will make the field accept NULL values. Blank values for Django field types such as DateTimeField or ForeignKey will be stored as NULL in the database.
Django-filter is a generic, reusable application to alleviate writing some of the more mundane bits of view code. Specifically, it allows users to filter down a queryset based on a model's fields, displaying the form to let them do this.
After Django 3.1 you can use EmptyFieldListFilter:
class MyAdmin(admin.ModelAdmin):
list_filter = (
("model_field", admin.EmptyFieldListFilter),
)
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 SimpleListFilter
class 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 queryset
class StartNullFilterSpec(NullFilterSpec):
title = u'Started'
parameter_name = u'started'
Than just used them in ModelAdmin:
class SomeModelAdmin(admin.ModelAdmin):
list_filter = (StartNullFilterSpec, )
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With