Custom filter in Django Admin on Django 1.3 or lower

How to add a custom filter to django admin (filters that appear on the right side of the model toolbar)? I know that it’s easy to enable a filter based on the field of this model, but what about the “calculated” field as follows:

class NewsItem(models.Model): headline = models.CharField(max_length=4096, blank=False) byline_1 = models.CharField(max_length=4096, blank=True) dateline = models.DateTimeField(help_text=_("date/time that appears on article")) body_copy = models.TextField(blank=False) when_to_publish = models.DateTimeField(verbose_name="When to publish", blank=True, null=True) # HOW CAN I HAVE "is_live" as part of the admin filter? It a calculated state!! 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 



 class NewsItemAdmin(admin.ModelAdmin): form = NewsItemAdminForm list_display = ('headline', 'id', 'is_live') list_filter = ('is_live') # how can i make this work?? 
+71
python django django-admin
Jun 14 '09 at 1:25
source share
8 answers

Thanks to gpilotino for giving me a push in the right direction to implement this.

I noticed that the question code uses date-time to figure out when it lives. So I used DateFieldFilterSpec and subclassed it.

 from django.db import models 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 IsLiveFilterSpec(DateFieldFilterSpec): """ Adds filtering by future and previous values in the admin filter sidebar. Set the is_live_filter filter in the model field attribute 'is_live_filter'. my_model_field.is_live_filter = True """ def __init__(self, f, request, params, model, model_admin): super(IsLiveFilterSpec, self).__init__(f, request, params, model, model_admin) 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 Live" # registering the filter FilterSpec.filter_specs.insert(0, (lambda f: getattr(f, 'is_live_filter', False), IsLiveFilterSpec)) 

To use, you can put the above code in the filters.py file and import it into the model that you want to add to the filter

+56
Aug 18 '09 at 16:19
source share

you need to write your own FilterSpec filter (not documented anywhere). Here is an example:

http://www.djangosnippets.org/snippets/1051/

+22
Aug 11 '09 at 13:25
source share

In the current version of django development, there is support for custom filters: https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_filter

+9
Jun 15 2018-11-11T00:
source share

You cannot, unfortunately. Currently, non-field items cannot be used as list_filter entries.

Please note that your admin class would not work even if this field is because a tuple with one element needs a comma: ('is_live',)

+3
Jun 14 '09 at 8:17
source share

Just sitting: you can use the deafult checkbox in the Django admin more easily:

 def is_live(self): if self.when_to_publish is not None: if ( self.when_to_publish < datetime.now() ): return True else: return False is_live.boolean = True 
+3
Dec 19 '13 at 9:49 on
source share

Not the optimal way (on CPU), but simple and will work, so I do it this way (for my small database). My version of Django is 1.6.

In admin.py:

 class IsLiveFilter(admin.SimpleListFilter): title = 'Live' parameter_name = 'islive' def lookups(self, request, model_admin): return ( ('1', 'islive'), ) def queryset(self, request, queryset): if self.value(): array = [] for element in queryset: if element.is_live.__call__() == True: q_array.append(element.id) return queryset.filter(pk__in=q_array) 

...

 class NewsItemAdmin(admin.ModelAdmin): form = NewsItemAdminForm list_display = ('headline', 'id', 'is_live') list_filter = (IsLiveFilter) 

The main idea here is to access custom fields in QuerySet using the __ call __ () function.

+3
Aug 18 '14 at 9:04 on
source share

The user delivers goods to some countries for free. I wanted to filter out these countries:

All - all countries, Yes - free scheduled delivery, No - paid postage.

The main answer for this question did not work for me (Django 1.3). I think because __init__ did not have a field_path parameter. It is also subclassed by DateFieldFilterSpec . postage field is FloatField

 from django.contrib.admin.filterspecs import FilterSpec class IsFreePostage(FilterSpec): def __init__(self, f, request, params, model, model_admin, field_path=None): super(IsFreePostage, self).__init__(f, request, params, model, model_admin, field_path) self.removes = { 'Yes': ['postage__gt'], 'No': ['postage__exact'], 'All': ['postage__exact', 'postage__gt'] } self.links = ( ('All', {}), ('Yes', {'postage__exact': 0}), ('No', {'postage__gt': 0})) if request.GET.has_key('postage__exact'): self.ttl = 'Yes' elif request.GET.has_key('postage__gt'): self.ttl = 'No' else: self.ttl = 'All' def choices(self, cl): for title, param_dict in self.links: yield {'selected': title == self.ttl, 'query_string': cl.get_query_string(param_dict, self.removes[title]), 'display': title} def title(self): return 'Free Postage' FilterSpec.filter_specs.insert(0, (lambda f: getattr(f, 'free_postage', False), IsFreePostage)) 

At self.links we supply dicts. used to build HTTP request strings, such as ?postage__exact=0 for each of the possible filters. Filters, I think, are cumulative, therefore, if there was a previous request “No”, and now we have a request “Yes”, we must delete the Request “No”. self.removes indicates what needs to be removed for each request. The choices method constructs query strings, indicates which filter was selected, and sets the display name of the filter.

+2
Oct 10 2018-11-12T00:
source share

Here is the answer and as simple user filter as possible, this can help

Django Date Range Filter

+1
Feb 10 '17 at 5:12
source share



All Articles