Example #1
0
    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 []
Example #2
0
 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))
Example #3
0
 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))
Example #4
0
    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])