Search code examples
djangodjango-admindjango-admin-filters

Custom Filter for Date Field in Django Admin, Django 1.2


Is this still valid syntax for Django 1.2?

Custom Filter in Django Admin on Django 1.3 or below

I have tried it, but the list_filter option in the admin class is not recognizing my custom filter. How should the custom filter be added to the list_filter so that it displays?

    class MyModelAdmin(admin.ModelAdmin):
        ...
        list_filter = ['is_expired_filter']

Here my 'is_expired_filter' is my newly registered custom filter, which is what the Author says he does like so:

    list_filter = ('is_live')

But this is not recognized by Django, and the error I get when I load the admin page is

Exception Type: ImproperlyConfigured Exception Value: 'PositionAdmin.list_filter[2]' refers to field 'is_expired_filter' that is missing from model 'Position'

Perhaps my mistake is that I am not sure how the original code is used by the Author of that question once he/she implements a custom filter.

Here is the original code:

    def is_live(self):
        if self.when_to_publish is not None:
            if ( self.when_to_publish < datetime.now() ):
                return """ <img alt="True" src="/media/img/admin/icon-yes.gif"/> """
        else:
            return """ <img alt="False" src="/media/img/admin/icon-no.gif"/> """      

    is_live.allow_tags = True

Solution

  • Now that I have a handle on what I think you want, I'm assuming you have a model that you want to filter by a DateField like:

    class Position(models.Model):
        expiration_date = models.DateField()
        ...
    

    which you should now modify to

    class Position(models.Model):
        expiration_date = models.DateField()
        expiration_date.is_expired_filter = True
        ...
    

    What you want to do is add to your admin.py a new filter class

    from django.contrib.admin.filterspecs import FilterSpec, DateFieldFilterSpec
    from django.utils.translation import ugettext as _
    from datetime import datetime, date
    class ExpiredFilterSpec(DateFieldFilterSpec):
        """
        Adds filtering by future and previous values in the admin
        filter sidebar. Set the is_expired_filter filter in the model field
        attribute 'is_expired_filter'.
        my_model_field.is_expired_filter = True
        """
        def __init__(self, f, request, params, model, model_admin, **kwargs):
            super(ExpiredFilterSpec, self).__init__(f, request, params, model,
                                                    model_admin, **kwargs)
            today = date.today()
            self.links = (
                (_('All'), {}),
                (_('Not Expired'), {'%s__lt' % self.field.name: str(today),
                       }),
                (_('Expired'), {'%s__gte' % self.field.name: str(today),
                        }))
        def title(self):
            return "Filter By Expiration Date"
    # registering the filter
    FilterSpec.filter_specs.insert(0, (lambda f: getattr(f, 'is_expired_filter', False),
                                       ExpiredFilterSpec))
    
    
    class PositionAdmin(admin.ModelAdmin):
        list_filter = ['expiration_date']