﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
15615	filterspec feature	duzy84@…	nobody	"
== Filter customization ==

The lack of filter customization in django admin documentation gives me the reason to write some sample. The filters are made on '''DateTimeFiled''' and distinguish objects by '''month''' and '''year'''. However each filter applied on one field works - applying them both is not familiar to me and I have no clue how to do this. One workaround is to make a fake field which is the copy of reference filed and apply the next filter on the fake, but for sure there is more elegant solution e.g changing GET request. The code suffers from lack of unit testing.

{{{#!python
#app/filters.py

from django.db import models
from django.contrib.admin.filterspecs import FilterSpec, DateFieldFilterSpec
from django.utils.translation import ugettext as _
import datetime

class MonthFilterSpec(DateFieldFilterSpec):

  def __init__(self, f, request, params, model, model_admin):
    super(MonthFilterSpec, self).__init__(f, request, params, model, model_admin)
    self.field_generic = '%s__' % self.field.name

    self.parsed_params = dict([(k, v) for k, v in params.items() if k.startswith(self.field_generic)])
    self.values = [int(v) for k, v in self.parsed_params.iteritems()]

    self.links = (
      (_('Any month'), {}),
      (_('January'), {'%s__month' % self.field.name: 1, }),
      (_('February'), {'%s__month' % self.field.name: 2, }),
      (_('March'), {'%s__month' % self.field.name: 3, }),
      (_('April'), {'%s__month' % self.field.name: 4, }),
      (_('May'), {'%s__month' % self.field.name: 5, }),
      (_('June'), {'%s__month' % self.field.name: 6, }),
      (_('July'), {'%s__month' % self.field.name: 7, }),
      (_('August'), {'%s__month' % self.field.name: 8, }),
      (_('September'), {'%s__month' % self.field.name: 9, }),
      (_('October'), {'%s__month' % self.field.name: 10, }),
      (_('November'), {'%s__month' % self.field.name: 11, }),
      (_('December'), {'%s__month' % self.field.name: 12, }),
    )

  def title(self):
    return _(""Month"")

  def choices(self, cl):
    for title, param_dict in self.links:
      yield {'selected':  param_dict.get('%s__month'%self.field.name, '') in self.values or param_dict==self.parsed_params,
             'query_string': cl.get_query_string(param_dict, [self.field.name]),
             'display': title}


class YearFilterSpec(DateFieldFilterSpec):

  def __init__(self, f, request, params, model, model_admin):
    super(YearFilterSpec, self).__init__(f, request, params, model, model_admin)
    year = int(datetime.date.today().year)

    self.field_generic = '%s__' % self.field.name
    self.parsed_params = dict([(k, v) for k, v in params.items() if k.startswith(self.field_generic)])
    self.values = [str(v) for k, v in self.parsed_params.items()]

    self.links = (
      (_('Any year'), {}),
      (_('%s'%str(year-1)), {'%s__year' % self.field.name: year-1, }),
      (_('%s'%str(year)), {'%s__year' % self.field.name: year, }),
      (_('%s'%str(year+1)), {'%s__year' % self.field.name: year+1, }),
    )


  def title(self):
    return _(""Year"")

  def choices(self, cl):
    for title, param_dict in self.links:
      yield {'selected':  title in self.values or param_dict==self.parsed_params,
             'query_string': cl.get_query_string(param_dict, [self.field.name]),
             'display': title}

                                                                                                                                                        
FilterSpec.filter_specs.insert(0, (lambda f: getattr(f, 'year_filter', False), YearFilterSpec))
FilterSpec.filter_specs.insert(0, (lambda f: getattr(f, 'month_filter', False), MonthFilterSpec))

#app/models.py
start = models.DateField(_('start'), unique_for_date=True)
start.month_filter = True
start.year_filter = True

#app/admin.py
from app.filters import MonthFilterSpec, YearFilterSpec
list_filter = ('start', )

}}}
"		closed	contrib.admin	1.2		duplicate	filter		Unreviewed	0	0	1	0	0	0
