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:
开发者_如何学Python 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
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']
Almost copying your link Custom Filter in Django Admin on Django 1.3 or below word for word, I came up with this.
from django.contrib.admin.filterspecs import FilterSpec, ChoicesFilterSpec, DateFieldFilterSpec
from django.utils.encoding import smart_unicode
from django.utils.translation import ugettext as _
from datetime import datetime
class IsExpiredFilterSpec(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):
super(IsExpiredFilterSpec, self).__init__(f, request, params, model,
model_admin)
# -- You'll need to edit this to make it do what you want. --
# today = datetime.now()
# self.links = (
# (_('Any'), {}),
# (_('Yes'), {'%s__lte' % self.field.name: str(today),
# }),
# (_('No'), {'%s__gte' % self.field.name: str(today),
# }),
#
# )
def title(self):
return "Is Expired"
\# registering the filter
FilterSpec.filter_specs.insert(0, (lambda f: getattr(f, 'is_expired_filter', False),
IsExpiredFilterSpec))
class MyModelAdmin(admin.ModelAdmin):
...
MODEL_FIELD_TO_FILTER.is_expired_filter = True
list_filters = ['MODEL_FIELD_TO_FILTER']
UPDATE: Made a change thanks to jimbob. MODEL_FIELD_TO_FILTER would be the field you want to filter.
精彩评论