Filtering Django Admin by Null/Is Not Null

后端 未结 7 1418
太阳男子
太阳男子 2020-12-16 15:03

I have a simple Django model like:

class Person(models.Model):
    referrer = models.ForeignKey(\'self\', null=True)
    ...

In this model\

相关标签:
7条回答
  • 2020-12-16 15:40

    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, )
    
    0 讨论(0)
  • 2020-12-16 15:40

    There has been a ticket bouncing around for this for 4 years (https://code.djangoproject.com/ticket/5833). It missed the 1.3 milestone, but has reached new feature status and presumably has found it's way into trunk. If you don't mind running off of trunk, you can use it now. The patch is supposedly 1.3 compatible, though, so you can probably get by with just patching your currently installation.

    0 讨论(0)
  • 2020-12-16 15:41

    there is a simple way:

    class RefererFilter(admin.SimpleListFilter):
        title = 'has referer'
        # Parameter for the filter that will be used in the URL query.
        parameter_name = 'referer__isnull'
    
        def lookups(self, request, model_admin):
            return (
                ('False', 'has referer'),
                ('True', 'has no referer'),
            )
    
        def queryset(self, request, queryset):
            if self.value() == 'False':
                return queryset.filter(referer__isnull=False)
            if self.value() == 'True':
                return queryset.filter(referer__isnull=True)
    

    Then just used them in ModelAdmin:

    class PersonAdmin(admin.ModelAdmin):
        list_filter =  (RefererFilter,) 
    
    0 讨论(0)
  • 2020-12-16 15:44

    After Django 3.1 you can use EmptyFieldListFilter:

    class MyAdmin(admin.ModelAdmin):
        list_filter =  (
            ("model_field", admin.EmptyFieldListFilter),
        )
    
    0 讨论(0)
  • 2020-12-16 15:59

    A snippet with a better explanation might be this. Django 1.4 will ship with a simplified filter mechanism.

    0 讨论(0)
  • 2020-12-16 16:07

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

    from django.contrib.admin import SimpleListFilter
    
    class 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')), )
    
    0 讨论(0)
提交回复
热议问题