Django

Code

Ticket #5833: 5833-against-9820.patch

File 5833-against-9820.patch, 11.4 kB (added by gerdemb, 1 year ago)

Patch updated to latest HEAD passing all tests

  • django/contrib/admin/filterspecs.py

    old new  
    1414import datetime 
    1515 
    1616class 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): 
    2019        self.params = params 
    2120 
    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  
    3221    def has_output(self): 
    3322        return True 
    3423 
     
    3625        raise NotImplementedError() 
    3726 
    3827    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         
    4033 
    4134    def output(self, cl): 
    4235        t = [] 
     
    5144            t.append('</ul>\n\n') 
    5245        return mark_safe("".join(t)) 
    5346 
    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) 
     47class 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 
     66class RelatedFilterSpec(FieldFilterSpec): 
     67    def __init__(self, request, params, model, model_admin, f): 
     68        super(RelatedFilterSpec, self).__init__(request, params, model, model_admin, f) 
    5769        if isinstance(f, models.ManyToManyField): 
    5870            self.lookup_title = f.rel.to._meta.verbose_name 
    5971        else: 
     
    7789                   'query_string': cl.get_query_string({self.lookup_kwarg: pk_val}), 
    7890                   'display': val} 
    7991 
    80 FilterSpec.register(lambda f: bool(f.rel), RelatedFilterSpec) 
     92FieldFilterSpec.register(lambda f: bool(f.rel), RelatedFilterSpec) 
    8193 
    82 class ChoicesFilterSpec(FilterSpec): 
    83     def __init__(self, f, request, params, model, model_admin): 
    84         super(ChoicesFilterSpec, self).__init__(f, request, params, model, model_admin
     94class ChoicesFilterSpec(FieldFilterSpec): 
     95    def __init__(self, request, params, model, model_admin, f): 
     96        super(ChoicesFilterSpec, self).__init__(request, params, model, model_admin, f
    8597        self.lookup_kwarg = '%s__exact' % f.name 
    8698        self.lookup_val = request.GET.get(self.lookup_kwarg, None) 
    8799 
     
    94106                    'query_string': cl.get_query_string({self.lookup_kwarg: k}), 
    95107                    'display': v} 
    96108 
    97 FilterSpec.register(lambda f: bool(f.choices), ChoicesFilterSpec) 
     109FieldFilterSpec.register(lambda f: bool(f.choices), ChoicesFilterSpec) 
    98110 
    99 class DateFieldFilterSpec(FilterSpec): 
    100     def __init__(self, f, request, params, model, model_admin): 
    101         super(DateFieldFilterSpec, self).__init__(f, request, params, model, model_admin
     111class DateFieldFilterSpec(FieldFilterSpec): 
     112    def __init__(self, request, params, model, model_admin, f): 
     113        super(DateFieldFilterSpec, self).__init__(request, params, model, model_admin, f
    102114 
    103115        self.field_generic = '%s__' % self.field.name 
    104116 
     
    129141                   'query_string': cl.get_query_string(param_dict, [self.field_generic]), 
    130142                   'display': title} 
    131143 
    132 FilterSpec.register(lambda f: isinstance(f, models.DateField), DateFieldFilterSpec) 
     144FieldFilterSpec.register(lambda f: isinstance(f, models.DateField), DateFieldFilterSpec) 
    133145 
    134 class BooleanFieldFilterSpec(FilterSpec): 
    135     def __init__(self, f, request, params, model, model_admin): 
    136         super(BooleanFieldFilterSpec, self).__init__(f, request, params, model, model_admin
     146class BooleanFieldFilterSpec(FieldFilterSpec): 
     147    def __init__(self, request, params, model, model_admin, f): 
     148        super(BooleanFieldFilterSpec, self).__init__(request, params, model, model_admin, f
    137149        self.lookup_kwarg = '%s__exact' % f.name 
    138150        self.lookup_kwarg2 = '%s__isnull' % f.name 
    139151        self.lookup_val = request.GET.get(self.lookup_kwarg, None) 
     
    152164                   'query_string': cl.get_query_string({self.lookup_kwarg2: 'True'}, [self.lookup_kwarg]), 
    153165                   'display': _('Unknown')} 
    154166 
    155 FilterSpec.register(lambda f: isinstance(f, models.BooleanField) or isinstance(f, models.NullBooleanField), BooleanFieldFilterSpec) 
     167FieldFilterSpec.register(lambda f: isinstance(f, models.BooleanField) or isinstance(f, models.NullBooleanField), BooleanFieldFilterSpec) 
    156168 
    157169# This should be registered last, because it's a last resort. For example, 
    158170# if a field is eligible to use the BooleanFieldFilterSpec, that'd be much 
    159171# more appropriate, and the AllValuesFilterSpec won't get used for it. 
    160 class AllValuesFilterSpec(FilterSpec): 
    161     def __init__(self, f, request, params, model, model_admin): 
    162         super(AllValuesFilterSpec, self).__init__(f, request, params, model, model_admin
     172class AllValuesFilterSpec(FieldFilterSpec): 
     173    def __init__(self, request, params, model, model_admin, f): 
     174        super(AllValuesFilterSpec, self).__init__(request, params, model, model_admin, f
    163175        self.lookup_val = request.GET.get(f.name, None) 
    164176        self.lookup_choices = model_admin.queryset(request).distinct().order_by(f.name).values(f.name) 
    165177 
     
    175187            yield {'selected': self.lookup_val == val, 
    176188                   'query_string': cl.get_query_string({self.field.name: val}), 
    177189                   'display': val} 
    178 FilterSpec.register(lambda f: True, AllValuesFilterSpec) 
     190FieldFilterSpec.register(lambda f: True, AllValuesFilterSpec) 
  • django/contrib/admin/validation.py

    old new  
    66from django.core.exceptions import ImproperlyConfigured 
    77from django.db import models 
    88from django.forms.models import BaseModelForm, BaseModelFormSet, fields_for_model 
     9from django.contrib.admin.filterspecs import FilterSpec, FieldFilterSpec 
    910from django.contrib.admin.options import flatten_fieldsets, BaseModelAdmin 
    1011from django.contrib.admin.options import HORIZONTAL, VERTICAL 
    1112 
     
    5657    # list_filter 
    5758    if hasattr(cls, 'list_filter'): 
    5859        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) 
    6177 
    6278    # list_per_page = 100 
    6379    if hasattr(cls, 'list_per_page') and not isinstance(cls.list_per_page, int): 
  • django/contrib/admin/views/main.py

    old new  
    1 from django.contrib.admin.filterspecs import FilterSpec 
     1from django.contrib.admin.filterspecs import FilterSpec, FieldFilterSpec 
    22from django.contrib.admin.options import IncorrectLookupParameters 
    33from django.contrib.admin.util import quote 
    44from django.core.paginator import Paginator, InvalidPage 
     
    6262        if ERROR_FLAG in self.params: 
    6363            del self.params[ERROR_FLAG] 
    6464 
     65        self.filter_specs, self.has_filters = self.get_filters(request) 
    6566        self.order_field, self.order_type = self.get_ordering() 
    6667        self.query = request.GET.get(SEARCH_VAR, '') 
    6768        self.query_set = self.get_query_set() 
    6869        self.get_results(request) 
    6970        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 
    7172        self.pk_attname = self.lookup_opts.pk.attname 
    7273 
    7374    def get_filters(self, request): 
    7475        filter_specs = [] 
    7576        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) 
    7988                if spec and spec.has_output(): 
    8089                    filter_specs.append(spec) 
    8190        return filter_specs, bool(filter_specs) 
     
    169178 
    170179    def get_query_set(self): 
    171180        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         
    172187        lookup_params = self.params.copy() # a dictionary of the query string 
    173188        for i in (ALL_VAR, ORDER_VAR, ORDER_TYPE_VAR, SEARCH_VAR, IS_POPUP_VAR): 
    174189            if i in lookup_params: 
     
    178193                # 'key' will be used as a keyword argument later, so Python 
    179194                # requires it to be a string. 
    180195                del lookup_params[key] 
    181                 lookup_params[smart_str(key)] = value 
     196                key = smart_str(key) 
     197                lookup_params[key] = value 
    182198 
    183199            # if key ends with __in, split parameter into separate values 
    184200            if key.endswith('__in'):