Opened 4 years ago

Closed 4 years ago

Last modified 3 years ago

#15615 closed (duplicate)

filterspec feature

Reported by: duzy84@… Owned by: nobody
Component: contrib.admin Version: 1.2
Severity: Keywords: filter
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: yes Patch needs improvement: no
Easy pickings: UI/UX:

Description

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.

#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', )

Change History (3)

comment:1 Changed 4 years ago by farciarz <duzy84@…>

  • milestone changed from 1.3 to 1.4
  • Needs documentation unset
  • Needs tests set
  • Patch needs improvement unset

comment:2 Changed 4 years ago by ramiro

  • Resolution set to duplicate
  • Status changed from new to closed

Duplicate of #5833.

comment:3 Changed 3 years ago by jacob

  • milestone 1.4 deleted

Milestone 1.4 deleted

Note: See TracTickets for help on using tickets.
Back to Top