def _check_list_filter_item(self, cls, model, item, label): """ Check one item of `list_filter`, i.e. check if it is one of three options: 1. 'field' -- a basic field filter, possibly w/ relationships (e.g. 'field__rel') 2. ('field', SomeFieldListFilter) - a field-based list filter class 3. SomeListFilter - a non-field list filter class """ from myrobogals.admin import ListFilter, FieldListFilter if callable(item) and not isinstance(item, models.Field): # If item is option 3, it should be a ListFilter... if not issubclass(item, ListFilter): return must_inherit_from(parent='ListFilter', option=label, obj=cls, id='admin.E113') # ... but not a FieldListFilter. elif issubclass(item, FieldListFilter): return [ checks.Error( "The value of '%s' must not inherit from 'FieldListFilter'." % label, hint=None, obj=cls, id='admin.E114', ) ] else: return [] elif isinstance(item, (tuple, list)): # item is option #2 field, list_filter_class = item if not issubclass(list_filter_class, FieldListFilter): return must_inherit_from(parent='FieldListFilter', option='%s[1]' % label, obj=cls, id='admin.E115') else: return [] else: # item is option #1 field = item # Validate the field string try: get_fields_from_path(model, field) except (NotRelationField, FieldDoesNotExist): return [ checks.Error( "The value of '%s' refers to '%s', which does not refer to a Field." % (label, field), hint=None, obj=cls, id='admin.E116', ) ] else: return []
def validate_list_filter(self, cls, model): """ Validate that list_filter is a sequence of one of three options: 1: 'field' - a basic field filter, possibly w/ relationships (eg, 'field__rel') 2: ('field', SomeFieldListFilter) - a field-based list filter class 3: SomeListFilter - a non-field list filter class """ from myrobogals.admin import ListFilter, FieldListFilter if hasattr(cls, 'list_filter'): check_isseq(cls, 'list_filter', cls.list_filter) for idx, item in enumerate(cls.list_filter): if callable(item) and not isinstance(item, models.Field): # If item is option 3, it should be a ListFilter... if not issubclass(item, ListFilter): raise ImproperlyConfigured( "'%s.list_filter[%d]' is '%s'" " which is not a descendant of ListFilter." % (cls.__name__, idx, item.__name__)) # ... but not a FieldListFilter. if issubclass(item, FieldListFilter): raise ImproperlyConfigured( "'%s.list_filter[%d]' is '%s'" " which is of type FieldListFilter but is not" " associated with a field name." % (cls.__name__, idx, item.__name__)) else: if isinstance(item, (tuple, list)): # item is option #2 field, list_filter_class = item if not issubclass(list_filter_class, FieldListFilter): raise ImproperlyConfigured( "'%s.list_filter[%d][1]'" " is '%s' which is not of type FieldListFilter." % (cls.__name__, idx, list_filter_class.__name__)) else: # item is option #1 field = item # Validate the field string try: get_fields_from_path(model, field) except (NotRelationField, FieldDoesNotExist): raise ImproperlyConfigured( "'%s.list_filter[%d]' refers to '%s'" " which does not refer to a Field." % (cls.__name__, idx, field))
def validate_list_filter(self, cls, model): """ Validate that list_filter is a sequence of one of three options: 1: 'field' - a basic field filter, possibly w/ relationships (eg, 'field__rel') 2: ('field', SomeFieldListFilter) - a field-based list filter class 3: SomeListFilter - a non-field list filter class """ from myrobogals.admin import ListFilter, FieldListFilter if hasattr(cls, 'list_filter'): check_isseq(cls, 'list_filter', cls.list_filter) for idx, item in enumerate(cls.list_filter): if callable(item) and not isinstance(item, models.Field): # If item is option 3, it should be a ListFilter... if not issubclass(item, ListFilter): raise ImproperlyConfigured("'%s.list_filter[%d]' is '%s'" " which is not a descendant of ListFilter." % (cls.__name__, idx, item.__name__)) # ... but not a FieldListFilter. if issubclass(item, FieldListFilter): raise ImproperlyConfigured("'%s.list_filter[%d]' is '%s'" " which is of type FieldListFilter but is not" " associated with a field name." % (cls.__name__, idx, item.__name__)) else: if isinstance(item, (tuple, list)): # item is option #2 field, list_filter_class = item if not issubclass(list_filter_class, FieldListFilter): raise ImproperlyConfigured("'%s.list_filter[%d][1]'" " is '%s' which is not of type FieldListFilter." % (cls.__name__, idx, list_filter_class.__name__)) else: # item is option #1 field = item # Validate the field string try: get_fields_from_path(model, field) except (NotRelationField, FieldDoesNotExist): raise ImproperlyConfigured("'%s.list_filter[%d]' refers to '%s'" " which does not refer to a Field." % (cls.__name__, idx, field))
def get_filters(self, request): lookup_params = self.get_filters_params() use_distinct = False for key, value in lookup_params.items(): if not self.model_admin.lookup_allowed(key, value): raise DisallowedModelAdminLookup("Filtering by %s not allowed" % key) filter_specs = [] if self.list_filter: for list_filter in self.list_filter: if callable(list_filter): # This is simply a custom list filter class. spec = list_filter(request, lookup_params, self.model, self.model_admin) else: field_path = None if isinstance(list_filter, (tuple, list)): # This is a custom FieldListFilter class for a given field. field, field_list_filter_class = list_filter else: # This is simply a field name, so use the default # FieldListFilter class that has been registered for # the type of the given field. field, field_list_filter_class = list_filter, FieldListFilter.create if not isinstance(field, models.Field): field_path = field field = get_fields_from_path(self.model, field_path)[-1] spec = field_list_filter_class(field, request, lookup_params, self.model, self.model_admin, field_path=field_path) # Check if we need to use distinct() use_distinct = (use_distinct or lookup_needs_distinct(self.lookup_opts, field_path)) if spec and spec.has_output(): filter_specs.append(spec) # At this point, all the parameters used by the various ListFilters # have been removed from lookup_params, which now only contains other # parameters passed via the query string. We now loop through the # remaining parameters both to ensure that all the parameters are valid # fields and to determine if at least one of them needs distinct(). If # the lookup parameters aren't real fields, then bail out. try: for key, value in lookup_params.items(): lookup_params[key] = prepare_lookup_value(key, value) use_distinct = (use_distinct or lookup_needs_distinct(self.lookup_opts, key)) return filter_specs, bool(filter_specs), lookup_params, use_distinct except FieldDoesNotExist as e: six.reraise(IncorrectLookupParameters, IncorrectLookupParameters(e), sys.exc_info()[2])