#5833: Custom FilterSpecs
-------------------------------------+-------------------------------------
               Reporter:             |        Owner:  jkocherhans
  Honza_Kral                         |       Status:  assigned
                   Type:  New        |    Component:  contrib.admin
  feature                            |     Severity:  Normal
              Milestone:             |     Keywords:  nfa-someday
                Version:  SVN        |  list_filter filterspec nfa-
             Resolution:             |  changelist ep2008
           Triage Stage:  Accepted   |    Has patch:  1
    Needs documentation:  1          |  Needs tests:  1
Patch needs improvement:  0          |
-------------------------------------+-------------------------------------

Comment (by julien):

 OK, so I've tweaked the patch some more and tried to come up with an API
 that's (hopefully) simple and easy to use, introducing a new
 `SimpleFilterSpec` class. Here's an example:

 {{{
 #!python

 # The model
 class Person(models.Model):
     name = models.CharField(max_length=100)
     age = models.PositiveIntegerField()


 from django.contrib.admin.filterspecs import SimpleFilterSpec

 # The custom filter spec
 class AgeCategoryFilterSpec(SimpleFilterSpec):

     def get_title(self):
         return u'age category'

     def get_choices(self, request):
         return (
             (u'0-19', u'0 to 19'),
             (u'20-39', u'20 to 39'),
             (u'40-over', u'40 and over'),
         )

     def get_query_set(self, cls, qs):
         age_category = self.get_value()
         if age_category == u'0-19':
             return qs.filter(age__gte=0, age__lte=19)
         if age_category == u'20-39':
             return qs.filter(age__gte=20, age__lte=39)
         if age_category == u'40-over':
             return qs.filter(age__gte=40)
         return qs

 # The admin
 class PersonAdmin(admin.ModelAdmin):
     list_display = ('name', 'age')
     list_filter = ('age', AgeCategoryFilterSpec,)
 }}}

 `SimpleFilterSpec` does all the boring work for you, i.e. yielding the
 iterator items when rendering the template, managing the query string both
 in and out, and fetching the requested value. All you need to provide is
 the title and the choices, and then you can filter the queryset based on
 the requested value. The lookup parameter defaults to the title slugified
 (i.e. "age-category" with the example above), although you can customise
 it by overriding the `get_lookup_parameter()` hook.

 I think this API would cover the majority of use cases. If you want
 something more eccentric then you can always directly extend the
 `FilterSpec` class.

 It's all implemented in the attached patch, including tests for this new
 feature.

 Also, here are some notable changes I've made:

 * I've renamed the `choices()` method to `_choices()` as I think it feels
 more like internal API, and also to avoid users mistakingly overriding it
 instead of the proposed new official `get_choices()` method.
 * The name of  the `title()` method didn't feel right so I've renamed it
 `get_title()`. Hopefully this is isn't considered backwards-incompatible
 (it's easily reversible if so).

 So that's it. At this stage I'd really like to get some feedback both on
 the API and on the implementation approach, so please let me know what you
 think. If people like it then I'll write more tests and get started with
 the doc.

-- 
Ticket URL: <http://code.djangoproject.com/ticket/5833#comment:114>
Django <http://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.

Reply via email to