Ticket #5833: 5833-against-9820.patch
File 5833-against-9820.patch, 11.4 KB (added by , 16 years ago) |
---|
-
django/contrib/admin/filterspecs.py
14 14 import datetime 15 15 16 16 class FilterSpec(object): 17 filter_specs = [] 18 def __init__(self, f, request, params, model, model_admin): 19 self.field = f 17 18 def __init__(self, request, params, model, model_admin): 20 19 self.params = params 21 20 22 def register(cls, test, factory):23 cls.filter_specs.append((test, factory))24 register = classmethod(register)25 26 def create(cls, f, request, params, model, model_admin):27 for test, factory in cls.filter_specs:28 if test(f):29 return factory(f, request, params, model, model_admin)30 create = classmethod(create)31 32 21 def has_output(self): 33 22 return True 34 23 … … 36 25 raise NotImplementedError() 37 26 38 27 def title(self): 39 return self.field.verbose_name 28 raise NotImplementedError() 29 30 def get_query_set(self, cl, qs): 31 return qs 32 40 33 41 34 def output(self, cl): 42 35 t = [] … … 51 44 t.append('</ul>\n\n') 52 45 return mark_safe("".join(t)) 53 46 54 class RelatedFilterSpec(FilterSpec): 55 def __init__(self, f, request, params, model, model_admin): 56 super(RelatedFilterSpec, self).__init__(f, request, params, model, model_admin) 47 class FieldFilterSpec(FilterSpec): 48 field_filter_specs = [] 49 def __init__(self, request, params, model, model_admin, field): 50 super(FieldFilterSpec, self).__init__(request, params, model, model_admin) 51 self.field = field 52 53 def register(cls, test, factory): 54 cls.field_filter_specs.append((test, factory)) 55 register = classmethod(register) 56 57 def title(self): 58 return self.field.verbose_name 59 60 def create(cls, request, params, model, model_admin, field): 61 for test, factory in cls.field_filter_specs: 62 if test(field): 63 return factory(request, params, model, model_admin, field) 64 create = classmethod(create) 65 66 class RelatedFilterSpec(FieldFilterSpec): 67 def __init__(self, request, params, model, model_admin, f): 68 super(RelatedFilterSpec, self).__init__(request, params, model, model_admin, f) 57 69 if isinstance(f, models.ManyToManyField): 58 70 self.lookup_title = f.rel.to._meta.verbose_name 59 71 else: … … 77 89 'query_string': cl.get_query_string({self.lookup_kwarg: pk_val}), 78 90 'display': val} 79 91 80 Fi lterSpec.register(lambda f: bool(f.rel), RelatedFilterSpec)92 FieldFilterSpec.register(lambda f: bool(f.rel), RelatedFilterSpec) 81 93 82 class ChoicesFilterSpec(Fi lterSpec):83 def __init__(self, f, request, params, model, model_admin):84 super(ChoicesFilterSpec, self).__init__( f, request, params, model, model_admin)94 class ChoicesFilterSpec(FieldFilterSpec): 95 def __init__(self, request, params, model, model_admin, f): 96 super(ChoicesFilterSpec, self).__init__(request, params, model, model_admin, f) 85 97 self.lookup_kwarg = '%s__exact' % f.name 86 98 self.lookup_val = request.GET.get(self.lookup_kwarg, None) 87 99 … … 94 106 'query_string': cl.get_query_string({self.lookup_kwarg: k}), 95 107 'display': v} 96 108 97 Fi lterSpec.register(lambda f: bool(f.choices), ChoicesFilterSpec)109 FieldFilterSpec.register(lambda f: bool(f.choices), ChoicesFilterSpec) 98 110 99 class DateFieldFilterSpec(Fi lterSpec):100 def __init__(self, f, request, params, model, model_admin):101 super(DateFieldFilterSpec, self).__init__( f, request, params, model, model_admin)111 class DateFieldFilterSpec(FieldFilterSpec): 112 def __init__(self, request, params, model, model_admin, f): 113 super(DateFieldFilterSpec, self).__init__(request, params, model, model_admin, f) 102 114 103 115 self.field_generic = '%s__' % self.field.name 104 116 … … 129 141 'query_string': cl.get_query_string(param_dict, [self.field_generic]), 130 142 'display': title} 131 143 132 Fi lterSpec.register(lambda f: isinstance(f, models.DateField), DateFieldFilterSpec)144 FieldFilterSpec.register(lambda f: isinstance(f, models.DateField), DateFieldFilterSpec) 133 145 134 class BooleanFieldFilterSpec(Fi lterSpec):135 def __init__(self, f, request, params, model, model_admin):136 super(BooleanFieldFilterSpec, self).__init__( f, request, params, model, model_admin)146 class BooleanFieldFilterSpec(FieldFilterSpec): 147 def __init__(self, request, params, model, model_admin, f): 148 super(BooleanFieldFilterSpec, self).__init__(request, params, model, model_admin, f) 137 149 self.lookup_kwarg = '%s__exact' % f.name 138 150 self.lookup_kwarg2 = '%s__isnull' % f.name 139 151 self.lookup_val = request.GET.get(self.lookup_kwarg, None) … … 152 164 'query_string': cl.get_query_string({self.lookup_kwarg2: 'True'}, [self.lookup_kwarg]), 153 165 'display': _('Unknown')} 154 166 155 Fi lterSpec.register(lambda f: isinstance(f, models.BooleanField) or isinstance(f, models.NullBooleanField), BooleanFieldFilterSpec)167 FieldFilterSpec.register(lambda f: isinstance(f, models.BooleanField) or isinstance(f, models.NullBooleanField), BooleanFieldFilterSpec) 156 168 157 169 # This should be registered last, because it's a last resort. For example, 158 170 # if a field is eligible to use the BooleanFieldFilterSpec, that'd be much 159 171 # more appropriate, and the AllValuesFilterSpec won't get used for it. 160 class AllValuesFilterSpec(Fi lterSpec):161 def __init__(self, f, request, params, model, model_admin):162 super(AllValuesFilterSpec, self).__init__( f, request, params, model, model_admin)172 class AllValuesFilterSpec(FieldFilterSpec): 173 def __init__(self, request, params, model, model_admin, f): 174 super(AllValuesFilterSpec, self).__init__(request, params, model, model_admin, f) 163 175 self.lookup_val = request.GET.get(f.name, None) 164 176 self.lookup_choices = model_admin.queryset(request).distinct().order_by(f.name).values(f.name) 165 177 … … 175 187 yield {'selected': self.lookup_val == val, 176 188 'query_string': cl.get_query_string({self.field.name: val}), 177 189 'display': val} 178 Fi lterSpec.register(lambda f: True, AllValuesFilterSpec)190 FieldFilterSpec.register(lambda f: True, AllValuesFilterSpec) -
django/contrib/admin/validation.py
6 6 from django.core.exceptions import ImproperlyConfigured 7 7 from django.db import models 8 8 from django.forms.models import BaseModelForm, BaseModelFormSet, fields_for_model 9 from django.contrib.admin.filterspecs import FilterSpec, FieldFilterSpec 9 10 from django.contrib.admin.options import flatten_fieldsets, BaseModelAdmin 10 11 from django.contrib.admin.options import HORIZONTAL, VERTICAL 11 12 … … 56 57 # list_filter 57 58 if hasattr(cls, 'list_filter'): 58 59 check_isseq(cls, 'list_filter', cls.list_filter) 59 for idx, field in enumerate(cls.list_filter): 60 get_field(cls, model, opts, 'list_filter[%d]' % idx, field) 60 for idx, item in enumerate(cls.list_filter): 61 if callable(item): 62 if(not issubclass(item,FilterSpec)): 63 raise ImproperlyConfigured("'%s.list_filter[%d]'" 64 "refers to '%s' which is not of type FilterSpec." 65 % (cls.__name__, idx, item.__name__)) 66 else: 67 if type(item) is tuple: 68 (field, factory) = item 69 if(not issubclass(factory,FieldFilterSpec)): 70 raise ImproperlyConfigured("'%s.list_filter[%d][1]'" 71 " refers to '%s' which is not of type FieldFilterSpec." 72 % (cls.__name__, idx, factory.__name__)) 73 else: 74 field = item 75 # validate field 76 get_field(cls, model, opts, 'list_filter[%d]' % idx, field) 61 77 62 78 # list_per_page = 100 63 79 if hasattr(cls, 'list_per_page') and not isinstance(cls.list_per_page, int): -
django/contrib/admin/views/main.py
1 from django.contrib.admin.filterspecs import FilterSpec 1 from django.contrib.admin.filterspecs import FilterSpec, FieldFilterSpec 2 2 from django.contrib.admin.options import IncorrectLookupParameters 3 3 from django.contrib.admin.util import quote 4 4 from django.core.paginator import Paginator, InvalidPage … … 62 62 if ERROR_FLAG in self.params: 63 63 del self.params[ERROR_FLAG] 64 64 65 self.filter_specs, self.has_filters = self.get_filters(request) 65 66 self.order_field, self.order_type = self.get_ordering() 66 67 self.query = request.GET.get(SEARCH_VAR, '') 67 68 self.query_set = self.get_query_set() 68 69 self.get_results(request) 69 70 self.title = (self.is_popup and ugettext('Select %s') % force_unicode(self.opts.verbose_name) or ugettext('Select %s to change') % force_unicode(self.opts.verbose_name)) 70 self.filter_specs, self.has_filters = self.get_filters(request) 71 71 72 self.pk_attname = self.lookup_opts.pk.attname 72 73 73 74 def get_filters(self, request): 74 75 filter_specs = [] 75 76 if self.list_filter: 76 filter_fields = [self.lookup_opts.get_field(field_name) for field_name in self.list_filter] 77 for f in filter_fields: 78 spec = FilterSpec.create(f, request, self.params, self.model, self.model_admin) 77 for item in self.list_filter: 78 if callable(item): 79 spec = item(request, self.params, self.model, self.model_admin) 80 else: 81 if type(item) is tuple: 82 (name, factory) = item 83 else: 84 name = item 85 factory = FieldFilterSpec.create 86 f = self.lookup_opts.get_field(name) 87 spec = factory(request, self.params, self.model, self.model_admin, f) 79 88 if spec and spec.has_output(): 80 89 filter_specs.append(spec) 81 90 return filter_specs, bool(filter_specs) … … 169 178 170 179 def get_query_set(self): 171 180 qs = self.root_query_set 181 182 # let every filter do its filtering 183 for filter_spec in self.filter_specs: 184 tqs = filter_spec.get_query_set(self, qs) 185 if tqs != None: qs = tqs 186 172 187 lookup_params = self.params.copy() # a dictionary of the query string 173 188 for i in (ALL_VAR, ORDER_VAR, ORDER_TYPE_VAR, SEARCH_VAR, IS_POPUP_VAR): 174 189 if i in lookup_params: … … 178 193 # 'key' will be used as a keyword argument later, so Python 179 194 # requires it to be a string. 180 195 del lookup_params[key] 181 lookup_params[smart_str(key)] = value 196 key = smart_str(key) 197 lookup_params[key] = value 182 198 183 199 # if key ends with __in, split parameter into separate values 184 200 if key.endswith('__in'):