Django

Code

Changeset 3136

Show
Ignore:
Timestamp:
06/16/06 14:42:06 (2 years ago)
Author:
adrian
Message:

Added AllValuesFilterSpec? to admin changelist filters, which lets you put any arbitrary field in Admin.list_filter. To determine the list of all available choices, Django does a SELECT DISTINCT. Note this is backwards-incompatible for people who have defined and registered their own FilterSpecs?, because each FilterSpec? now takes a 'model' parameter.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/trunk/django/contrib/admin/filterspecs.py

    r2809 r3136  
    1212class FilterSpec(object): 
    1313    filter_specs = [] 
    14     def __init__(self, f, request, params): 
     14    def __init__(self, f, request, params, model): 
    1515        self.field = f 
    1616        self.params = params 
    1717 
    1818    def register(cls, test, factory): 
    19         cls.filter_specs.append( (test, factory)
     19        cls.filter_specs.append((test, factory)
    2020    register = classmethod(register) 
    2121 
    22     def create(cls, f, request, params): 
     22    def create(cls, f, request, params, model): 
    2323        for test, factory in cls.filter_specs: 
    2424            if test(f): 
    25                 return factory(f, request, params
     25                return factory(f, request, params, model
    2626    create = classmethod(create) 
    2727 
     
    4949 
    5050class RelatedFilterSpec(FilterSpec): 
    51     def __init__(self, f, request, params): 
    52         super(RelatedFilterSpec, self).__init__(f, request, params
     51    def __init__(self, f, request, params, model): 
     52        super(RelatedFilterSpec, self).__init__(f, request, params, model
    5353        if isinstance(f, models.ManyToManyField): 
    5454            self.lookup_title = f.rel.to._meta.verbose_name 
     
    7272            pk_val = getattr(val, self.field.rel.to._meta.pk.attname) 
    7373            yield {'selected': self.lookup_val == str(pk_val), 
    74                    'query_string': cl.get_query_string( {self.lookup_kwarg: pk_val}), 
     74                   'query_string': cl.get_query_string({self.lookup_kwarg: pk_val}), 
    7575                   'display': val} 
    7676 
     
    7878 
    7979class ChoicesFilterSpec(FilterSpec): 
    80     def __init__(self, f, request, params): 
    81         super(ChoicesFilterSpec, self).__init__(f, request, params
     80    def __init__(self, f, request, params, model): 
     81        super(ChoicesFilterSpec, self).__init__(f, request, params, model
    8282        self.lookup_kwarg = '%s__exact' % f.name 
    8383        self.lookup_val = request.GET.get(self.lookup_kwarg, None) 
     
    8585    def choices(self, cl): 
    8686        yield {'selected': self.lookup_val is None, 
    87                'query_string': cl.get_query_string( {}, [self.lookup_kwarg]), 
     87               'query_string': cl.get_query_string({}, [self.lookup_kwarg]), 
    8888               'display': _('All')} 
    8989        for k, v in self.field.choices: 
    9090            yield {'selected': str(k) == self.lookup_val, 
    91                     'query_string': cl.get_query_string( {self.lookup_kwarg: k}), 
     91                    'query_string': cl.get_query_string({self.lookup_kwarg: k}), 
    9292                    'display': v} 
    9393 
     
    9595 
    9696class DateFieldFilterSpec(FilterSpec): 
    97     def __init__(self, f, request, params): 
    98         super(DateFieldFilterSpec, self).__init__(f, request, params
     97    def __init__(self, f, request, params, model): 
     98        super(DateFieldFilterSpec, self).__init__(f, request, params, model
    9999 
    100100        self.field_generic = '%s__' % self.field.name 
     
    124124        for title, param_dict in self.links: 
    125125            yield {'selected': self.date_params == param_dict, 
    126                    'query_string': cl.get_query_string( param_dict, self.field_generic), 
     126                   'query_string': cl.get_query_string(param_dict, self.field_generic), 
    127127                   'display': title} 
    128128 
     
    130130 
    131131class BooleanFieldFilterSpec(FilterSpec): 
    132     def __init__(self, f, request, params): 
    133         super(BooleanFieldFilterSpec, self).__init__(f, request, params
     132    def __init__(self, f, request, params, model): 
     133        super(BooleanFieldFilterSpec, self).__init__(f, request, params, model
    134134        self.lookup_kwarg = '%s__exact' % f.name 
    135135        self.lookup_kwarg2 = '%s__isnull' % f.name 
     
    143143        for k, v in ((_('All'), None), (_('Yes'), '1'), (_('No'), '0')): 
    144144            yield {'selected': self.lookup_val == v and not self.lookup_val2, 
    145                    'query_string': cl.get_query_string( {self.lookup_kwarg: v}, [self.lookup_kwarg2]), 
     145                   'query_string': cl.get_query_string({self.lookup_kwarg: v}, [self.lookup_kwarg2]), 
    146146                   'display': k} 
    147147        if isinstance(self.field, models.NullBooleanField): 
    148148            yield {'selected': self.lookup_val2 == 'True', 
    149                    'query_string': cl.get_query_string( {self.lookup_kwarg2: 'True'}, [self.lookup_kwarg]), 
     149                   'query_string': cl.get_query_string({self.lookup_kwarg2: 'True'}, [self.lookup_kwarg]), 
    150150                   'display': _('Unknown')} 
    151151 
    152152FilterSpec.register(lambda f: isinstance(f, models.BooleanField) or isinstance(f, models.NullBooleanField), BooleanFieldFilterSpec) 
     153 
     154# This should be registered last, because it's a last resort. For example, 
     155# if a field is eligible to use the BooleanFieldFilterSpec, that'd be much 
     156# more appropriate, and the AllValuesFilterSpec won't get used for it. 
     157class AllValuesFilterSpec(FilterSpec): 
     158    def __init__(self, f, request, params, model): 
     159        super(AllValuesFilterSpec, self).__init__(f, request, params, model) 
     160        self.lookup_val = request.GET.get(f.name, None) 
     161        self.lookup_choices = model._meta.admin.manager.distinct().order_by(f.name).values(f.name) 
     162 
     163    def title(self): 
     164        return self.field.verbose_name 
     165 
     166    def choices(self, cl): 
     167        yield {'selected': self.lookup_val is None, 
     168               'query_string': cl.get_query_string({}, [self.field.name]), 
     169               'display': _('All')} 
     170        for val in self.lookup_choices: 
     171            val = str(val[self.field.name]) 
     172            yield {'selected': self.lookup_val == val, 
     173                   'query_string': cl.get_query_string({self.field.name: val}), 
     174                   'display': val} 
     175FilterSpec.register(lambda f: True, AllValuesFilterSpec) 
  • django/trunk/django/contrib/admin/views/main.py

    r3070 r3136  
    575575                              for field_name in self.lookup_opts.admin.list_filter] 
    576576            for f in filter_fields: 
    577                 spec = FilterSpec.create(f, request, self.params
     577                spec = FilterSpec.create(f, request, self.params, self.model
    578578                if spec and spec.has_output(): 
    579579                    filter_specs.append(spec)