Ticket #3400: 3400-against-10706.2.diff
File 3400-against-10706.2.diff, 10.5 KB (added by , 15 years ago) |
---|
-
django/contrib/admin/filterspecs.py
diff --git a/django/contrib/admin/filterspecs.py b/django/contrib/admin/filterspecs.py index 6f643ee..7f473a2 100644
a b import datetime 15 15 16 16 class FilterSpec(object): 17 17 filter_specs = [] 18 def __init__(self, f, request, params, model, model_admin ):18 def __init__(self, f, request, params, model, model_admin, field_path=None): 19 19 self.field = f 20 20 self.params = params 21 self.field_path = field_path or f.name 21 22 22 23 def register(cls, test, factory): 23 24 cls.filter_specs.append((test, factory)) 24 25 register = classmethod(register) 25 26 26 def create(cls, f, request, params, model, model_admin ):27 def create(cls, f, request, params, model, model_admin, field_path=None): 27 28 for test, factory in cls.filter_specs: 28 29 if test(f): 29 return factory(f, request, params, model, model_admin )30 return factory(f, request, params, model, model_admin, field_path=field_path) 30 31 create = classmethod(create) 31 32 32 33 def has_output(self): … … class FilterSpec(object): 52 53 return mark_safe("".join(t)) 53 54 54 55 class RelatedFilterSpec(FilterSpec): 55 def __init__(self, f, request, params, model, model_admin ):56 super(RelatedFilterSpec, self).__init__(f, request, params, model, model_admin )56 def __init__(self, f, request, params, model, model_admin, field_path=None): 57 super(RelatedFilterSpec, self).__init__(f, request, params, model, model_admin, field_path=field_path) 57 58 if isinstance(f, models.ManyToManyField): 58 59 self.lookup_title = f.rel.to._meta.verbose_name 59 60 else: 60 61 self.lookup_title = f.verbose_name 61 rel_name = f.rel. get_related_field().name62 self.lookup_kwarg = '%s__%s__exact' % ( f.name, rel_name)62 rel_name = f.rel.to._meta.pk.name 63 self.lookup_kwarg = '%s__%s__exact' % (self.field_path, rel_name) 63 64 self.lookup_val = request.GET.get(self.lookup_kwarg, None) 64 65 self.lookup_choices = f.get_choices(include_blank=False) 65 66 … … class RelatedFilterSpec(FilterSpec): 81 82 FilterSpec.register(lambda f: bool(f.rel), RelatedFilterSpec) 82 83 83 84 class ChoicesFilterSpec(FilterSpec): 84 def __init__(self, f, request, params, model, model_admin ):85 super(ChoicesFilterSpec, self).__init__(f, request, params, model, model_admin )86 self.lookup_kwarg = '%s__exact' % f.name85 def __init__(self, f, request, params, model, model_admin, field_path=None): 86 super(ChoicesFilterSpec, self).__init__(f, request, params, model, model_admin, field_path=field_path) 87 self.lookup_kwarg = '%s__exact' % self.field_path 87 88 self.lookup_val = request.GET.get(self.lookup_kwarg, None) 88 89 89 90 def choices(self, cl): … … class ChoicesFilterSpec(FilterSpec): 98 99 FilterSpec.register(lambda f: bool(f.choices), ChoicesFilterSpec) 99 100 100 101 class DateFieldFilterSpec(FilterSpec): 101 def __init__(self, f, request, params, model, model_admin ):102 super(DateFieldFilterSpec, self).__init__(f, request, params, model, model_admin )102 def __init__(self, f, request, params, model, model_admin, field_path=None): 103 super(DateFieldFilterSpec, self).__init__(f, request, params, model, model_admin, field_path=field_path) 103 104 104 self.field_generic = '%s__' % self.field .name105 self.field_generic = '%s__' % self.field_path 105 106 106 107 self.date_params = dict([(k, v) for k, v in params.items() if k.startswith(self.field_generic)]) 107 108 … … class DateFieldFilterSpec(FilterSpec): 111 112 112 113 self.links = ( 113 114 (_('Any date'), {}), 114 (_('Today'), {'%s__year' % self.field .name: str(today.year),115 '%s__month' % self.field .name: str(today.month),116 '%s__day' % self.field .name: str(today.day)}),117 (_('Past 7 days'), {'%s__gte' % self.field .name: one_week_ago.strftime('%Y-%m-%d'),118 '%s__lte' % f.name: today_str}),119 (_('This month'), {'%s__year' % self.field .name: str(today.year),120 '%s__month' % f.name: str(today.month)}),121 (_('This year'), {'%s__year' % self.field .name: str(today.year)})115 (_('Today'), {'%s__year' % self.field_path: str(today.year), 116 '%s__month' % self.field_path: str(today.month), 117 '%s__day' % self.field_path: str(today.day)}), 118 (_('Past 7 days'), {'%s__gte' % self.field_path: one_week_ago.strftime('%Y-%m-%d'), 119 '%s__lte' % self.field_path: today_str}), 120 (_('This month'), {'%s__year' % self.field_path: str(today.year), 121 '%s__month' % self.field_path: str(today.month)}), 122 (_('This year'), {'%s__year' % self.field_path: str(today.year)}) 122 123 ) 123 124 124 125 def title(self): … … class DateFieldFilterSpec(FilterSpec): 133 134 FilterSpec.register(lambda f: isinstance(f, models.DateField), DateFieldFilterSpec) 134 135 135 136 class BooleanFieldFilterSpec(FilterSpec): 136 def __init__(self, f, request, params, model, model_admin ):137 super(BooleanFieldFilterSpec, self).__init__(f, request, params, model, model_admin )138 self.lookup_kwarg = '%s__exact' % f.name139 self.lookup_kwarg2 = '%s__isnull' % f.name137 def __init__(self, f, request, params, model, model_admin, field_path=None): 138 super(BooleanFieldFilterSpec, self).__init__(f, request, params, model, model_admin, field_path=field_path) 139 self.lookup_kwarg = '%s__exact' % self.field_path 140 self.lookup_kwarg2 = '%s__isnull' % self.field_path 140 141 self.lookup_val = request.GET.get(self.lookup_kwarg, None) 141 142 self.lookup_val2 = request.GET.get(self.lookup_kwarg2, None) 142 143 … … FilterSpec.register(lambda f: isinstance(f, models.BooleanField) or isinstance(f 159 160 # if a field is eligible to use the BooleanFieldFilterSpec, that'd be much 160 161 # more appropriate, and the AllValuesFilterSpec won't get used for it. 161 162 class AllValuesFilterSpec(FilterSpec): 162 def __init__(self, f, request, params, model, model_admin): 163 super(AllValuesFilterSpec, self).__init__(f, request, params, model, model_admin) 164 self.lookup_val = request.GET.get(f.name, None) 165 self.lookup_choices = model_admin.queryset(request).distinct().order_by(f.name).values(f.name) 163 def __init__(self, f, request, params, model, model_admin, field_path=None): 164 super(AllValuesFilterSpec, self).__init__(f, request, params, model, model_admin, field_path=field_path) 165 self.lookup_val = request.GET.get(self.field_path, None) 166 #self.lookup_choices = model_admin.queryset(request).distinct().order_by(f.name).values(f.name) 167 self.lookup_choices = model._default_manager.all().distinct().order_by(f.name).values(f.name) 166 168 167 169 def title(self): 168 170 return self.field.verbose_name 169 171 170 172 def choices(self, cl): 171 173 yield {'selected': self.lookup_val is None, 172 'query_string': cl.get_query_string({}, [self.field .name]),174 'query_string': cl.get_query_string({}, [self.field_path]), 173 175 'display': _('All')} 174 176 for val in self.lookup_choices: 175 177 val = smart_unicode(val[self.field.name]) 176 178 yield {'selected': self.lookup_val == val, 177 'query_string': cl.get_query_string({self.field .name: val}),179 'query_string': cl.get_query_string({self.field_path: val}), 178 180 'display': val} 179 181 FilterSpec.register(lambda f: True, AllValuesFilterSpec) -
django/contrib/admin/validation.py
diff --git a/django/contrib/admin/validation.py b/django/contrib/admin/validation.py index 94d4bbd..88cae19 100644
a b def check_isdict(cls, label, obj): 324 324 325 325 def get_field(cls, model, opts, label, field): 326 326 try: 327 return opts.get_field(field) 327 if '__' in field: 328 f = None 329 m = model 330 path = field.split('__') 331 for field_name in path[:-1]: 332 f = model._meta.get_field(field_name) 333 model = f.rel.to 334 return opts.get_field(path[0]) 335 else: 336 return opts.get_field(field) 328 337 except models.FieldDoesNotExist: 329 338 raise ImproperlyConfigured("'%s.%s' refers to field '%s' that is missing from model '%s'." 330 339 % (cls.__name__, label, field, model.__name__)) -
django/contrib/admin/views/main.py
diff --git a/django/contrib/admin/views/main.py b/django/contrib/admin/views/main.py index df0fd9f..4300fd5 100644
a b class ChangeList(object): 74 74 def get_filters(self, request): 75 75 filter_specs = [] 76 76 if self.list_filter: 77 filter_fields = [self.lookup_opts.get_field(field_name) for field_name in self.list_filter] 78 for f in filter_fields: 79 spec = FilterSpec.create(f, request, self.params, self.model, self.model_admin) 77 lookup_opts = self.lookup_opts 78 for filter_name in self.list_filter: 79 if '__' in filter_name: 80 f = None 81 model = self.model 82 path = filter_name.split('__') 83 for field_index in xrange(len(path)-1): 84 f = model._meta.get_field(path[field_index]) 85 model = f.rel.to 86 f = model._meta.get_field(path[field_index+1]) 87 spec = FilterSpec.create(f, request, self.params, model, self.model_admin, field_path=filter_name) 88 else: 89 f = lookup_opts.get_field(filter_name) 90 spec = FilterSpec.create(f, request, self.params, self.model, self.model_admin) 80 91 if spec and spec.has_output(): 81 92 filter_specs.append(spec) 82 93 return filter_specs, bool(filter_specs) -
docs/ref/contrib/admin/index.txt
diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt index cacadfd..e75812c 100644
a b how both ``list_display`` and ``list_filter`` work:: 461 461 list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff') 462 462 list_filter = ('is_staff', 'is_superuser') 463 463 464 In ``list_filter`` can be defined lookup separator as well:: 465 466 class UserAdminWithLookup(UserAdmin): 467 list_filter = ('groups__name') 468 464 469 The above code results in an admin change list page that looks like this: 465 470 466 471 .. image:: _images/users_changelist.png