Example #1
0
    def _get_resource_filter(self, identifiers_prefix, identifiers, model, resource, request, filters_fields_rfs):
        """
        :param identifiers_prefix: because filters are recursive if model relations property contains list of
               identifiers that was used for recursive searching the filter.
        :param identifiers: list of identifiers that conclusively identifies the filter.
        :param model: django model class.
        :param resource: resource object.
        :param request: django HTTP request.
        :param filters_fields_rfs: RFS of fields that is allowed to filter.
        :return: method returns filter that is obtained from resource and its methods.
        """
        # Filter is obtained from resource filters dict
        for i in range(1, len(identifiers) + 1):
            # Because resource filters can contains filter key with __ we must try all combinations with suffixes
            current_identifiers = identifiers[:i]
            identifiers_string = LOOKUP_SEP.join(current_identifiers)
            identifiers_suffix = identifiers[i:]
            suffix_string = LOOKUP_SEP.join(identifiers_suffix)
            if (resource and identifiers_string in resource.filters and
                    (not suffix_string or suffix_string in resource.filters[identifiers_string].get_suffixes())):
                return resource.filters[identifiers_string](identifiers_prefix, current_identifiers, identifiers_suffix)

        # Filter is obtained from resource methods
        current_identifier = identifiers[0]
        resource_method = get_method_or_none(resource, current_identifier)

        if current_identifier in filters_fields_rfs and resource_method:
            return self._get_method_filter(resource_method, identifiers_suffix, [current_identifier], identifiers[1:],
                                           model, resource, request, filters_fields_rfs)

        return None
Example #2
0
    def _get_resource_filter(self, identifiers_prefix, identifiers, model, resource, request, filters_fields_rfs):
        """
        :param identifiers_prefix: because filters are recursive if model relations property contains list of
               identifiers that was used for recursive searching the filter.
        :param identifiers: list of identifiers that conclusively identifies the filter.
        :param model: django model class.
        :param resource: resource object.
        :param request: django HTTP request.
        :param filters_fields_rfs: RFS of fields that is allowed to filter.
        :return: method returns filter that is obtained from resource and its methods.
        """

        # Filter is obtained from resource filters dict
        for i in range(1, len(identifiers) + 1):
            # Because resource filters can contains filter key with __ we must try all combinations with suffixes
            current_identifiers = identifiers[:i]
            identifiers_string = self._get_real_field_name(resource, LOOKUP_SEP.join(current_identifiers))
            identifiers_suffix = identifiers[i:]
            suffix_string = LOOKUP_SEP.join(identifiers_suffix)
            if (resource and identifiers_string in resource.filters and
                    (not suffix_string or suffix_string in resource.filters[identifiers_string].get_suffixes())):
                return resource.filters[identifiers_string](
                    identifiers_prefix, current_identifiers, identifiers_suffix, model
                )

        # Filter is obtained from resource methods
        current_identifier = self._get_real_field_name(resource, identifiers[0])
        resource_method = resource.get_method_returning_field_value(current_identifier) if resource else None
        if current_identifier in filters_fields_rfs and resource_method:
            return self._get_method_filter(
                resource_method, identifiers_suffix, [current_identifier], identifiers[1:], model, resource, request,
                filters_fields_rfs
            )

        return None
Example #3
0
    def _get_sorter_from_resource(self, identifiers_prefix, identifiers,
                                  direction, model, resource, request,
                                  order_fields_rfs):
        """
        :param identifiers_prefix: because order strings are recursive if model relations property contains list of
               identifiers that was used for recursive searching the order string.
        :param identifiers: list of identifiers that conclusively identifies order string.
        :param direction: direction of ordering ASC or DESC.
        :param model: django model class.
        :param resource: resource object.
        :param request: django HTTP request.
        :param order_fields_rfs: RFS of fields that is allowed to order.
        :return: db order method string that is obtained from resource object.
        """
        full_identifiers_string = self._get_real_field_name(
            resource, LOOKUP_SEP.join(identifiers))

        resource_method = resource.get_method_returning_field_value(
            full_identifiers_string) if resource else None
        if full_identifiers_string in order_fields_rfs and resource_method:
            return self._get_sorter_from_method(resource_method,
                                                identifiers_prefix,
                                                identifiers, direction, model,
                                                resource, request,
                                                order_fields_rfs)
Example #4
0
    def _get_model_filter(self, identifiers_prefix, identifiers, model, resource, request, filters_fields_rfs):
        """
        :param identifiers_prefix: because filters are recursive if model relations property contains list of
               identifiers that was used for recursive searching the filter.
        :param identifiers: list of identifiers that conclusively identifies the filter.
        :param model: django model class.
        :param resource: resource object.
        :param request: django HTTP request.
        :param filters_fields_rfs: RFS of fields that is allowed to filter.
        :return: method returns filter from model fields or methods
        """
        current_identifier = identifiers[0]
        identifiers_suffix = identifiers[1:]

        if current_identifier not in filters_fields_rfs:
            raise FilterIdentifierError

        suffix = LOOKUP_SEP.join(identifiers_suffix)

        model_field = get_field_or_none(model, current_identifier)
        model_method = get_method_or_none(model, current_identifier)

        if model_field and model_field.filter and (not suffix or suffix in model_field.filter.get_suffixes()):
            return model_field.filter(identifiers_prefix, [current_identifier], identifiers_suffix, field=model_field)
        elif model_field and model_field.is_relation and model_field.related_model:
            # recursive search for filter via related model fields
            next_model = model_field.related_model
            next_resource = get_resource_or_none(request, next_model, getattr(resource, 'resource_typemapper'))
            return self._get_filter_recursive(
                identifiers_prefix + [identifiers[0]], identifiers[1:], next_model, next_resource, request,
                filters_fields_rfs[current_identifier].subfieldset
            )
        elif model_method:
            return self._get_method_filter(model_method, identifiers_prefix, [current_identifier], identifiers_suffix,
                                           model, resource, request, filters_fields_rfs)
Example #5
0
 def _get_method_filter(self, method, identifiers_prefix, identifiers, identifiers_suffix, model, resource, request,
                        filters_fields_rfs):
     """
     :param method: method from which we can get filter.
     :param identifiers_prefix: because filters are recursive if model relations property contains list of
            identifiers that was used for recursive searching the filter.
     :param identifiers: list of identifiers that conclusively identifies the filter.
     :param identifiers_suffix: list of suffixes that can be used for more specific filters.
     :param model: django model class.
     :param resource: resource object.
     :param request: django HTTP request.
     :param filters_fields_rfs: RFS of fields that is allowed to filter.
     :return: method returns filter object that is obtained from method.
     """
     if hasattr(method, 'filter_by'):
         # If method has filter_by attribute filter is being searched according to this value.
         filter_by_identifiers = method.filter_by.split(LOOKUP_SEP)
         next_identifiers = filter_by_identifiers + identifiers_suffix
         # Because method must be inside allowed filter fields RFS, we must add value filter_by of the method
         # to the next RFS.
         next_filters_fields_rfs = rfs(filter_by_identifiers)
         return self._get_filter_recursive(
             identifiers_prefix, next_identifiers, model, resource, request, next_filters_fields_rfs
         )
     suffix = LOOKUP_SEP.join(identifiers_suffix)
     if not hasattr(method, 'filter') or (suffix and suffix not in method.filter.get_suffixes()):
         raise FilterIdentifierError
     return method.filter(identifiers_prefix, identifiers, identifiers_suffix, method=method)
Example #6
0
 def _get_method_filter(self, method, identifiers_prefix, identifiers,
                        identifiers_suffix, model, resource, request,
                        filters_fields_rfs):
     """
     :param method: method from which we can get filter.
     :param identifiers_prefix: because filters are recursive if model relations property contains list of
            identifiers that was used for recursive searching the filter.
     :param identifiers: list of identifiers that conclusively identifies the filter.
     :param identifiers_suffix: list of suffixes that can be used for more specific filters.
     :param model: django model class.
     :param resource: resource object.
     :param request: django HTTP request.
     :param filters_fields_rfs: RFS of fields that is allowed to filter.
     :return: method returns filter object that is obtained from method.
     """
     if hasattr(method, 'filter_by'):
         # If method has filter_by attribute filter is being searched according to this value.
         filter_by_identifiers = method.filter_by.split(LOOKUP_SEP)
         next_identifiers = filter_by_identifiers + identifiers_suffix
         # Because method must be inside allowed filter fields RFS, we must add value filter_by of the method
         # to the next RFS.
         next_filters_fields_rfs = rfs(filter_by_identifiers)
         return self._get_filter_recursive(identifiers_prefix,
                                           next_identifiers, model,
                                           resource, request,
                                           next_filters_fields_rfs)
     suffix = LOOKUP_SEP.join(identifiers_suffix)
     if not hasattr(method, 'filter') or (
             suffix and suffix not in method.filter.get_suffixes()):
         raise FilterIdentifierError
     return method.filter(identifiers_prefix,
                          identifiers,
                          identifiers_suffix,
                          method=method)
Example #7
0
    def _get_order_string_from_model(self, identifiers_prefix, identifiers, model, resource, request, order_fields_rfs):
        """
        :param identifiers_prefix: because order strings are recursive if model relations property contains list of
               identifiers that was used for recursive searching the order string.
        :param identifiers: list of identifiers that conclusively identifies order string.
        :param model: django model class.
        :param resource: resource object.
        :param request: django HTTP request.
        :param order_fields_rfs: RFS of fields that is allowed to order.
        :return: db order method string that is obtained from model fields or methods.
        """
        current_identifier = identifiers[0]
        identifiers_suffix = identifiers[1:]

        if current_identifier not in order_fields_rfs:
            raise OrderIdentifierError

        model_field = get_field_or_none(model, current_identifier)
        model_method = get_method_or_none(model, current_identifier)

        if model_field and not identifiers_suffix and (not model_field.is_relation or model_field.related_model):
            return LOOKUP_SEP.join(identifiers_prefix + identifiers)
        elif model_field and model_field.is_relation and model_field.related_model:
            next_model = model_field.related_model
            next_resource = get_resource_or_none(request, next_model, getattr(resource, 'resource_typemapper'))
            return self._get_order_string_recursive(
                identifiers_prefix + [identifiers[0]], identifiers[1:],
                next_model, next_resource, request, order_fields_rfs[current_identifier].subfieldset
            )
        elif model_method and not identifiers_suffix:
            return self._get_order_string_from_method(
                model_method, identifiers_prefix, identifiers, model, resource, request, order_fields_rfs
            )
Example #8
0
    def _get_order_string_from_model(self, identifiers_prefix, identifiers, model, resource, request, order_fields_rfs):
        """
        :param identifiers_prefix: because order strings are recursive if model relations property contains list of
               identifiers that was used for recursive searching the order string.
        :param identifiers: list of identifiers that conclusively identifies order string.
        :param model: django model class.
        :param resource: resource object.
        :param request: django HTTP request.
        :param order_fields_rfs: RFS of fields that is allowed to order.
        :return: db order method string that is obtained from model fields or methods.
        """
        current_identifier = identifiers[0]
        identifiers_suffix = identifiers[1:]

        if current_identifier not in order_fields_rfs:
            raise OrderIdentifierError

        model_field = get_field_or_none(model, current_identifier)
        model_method = get_method_or_none(model, current_identifier)

        if model_field and not identifiers_suffix and (not model_field.is_relation or model_field.related_model):
            return LOOKUP_SEP.join(identifiers_prefix + identifiers)
        elif model_field and model_field.is_relation and model_field.related_model:
            next_model = model_field.related_model
            next_resource = get_resource_or_none(request, next_model, getattr(resource, 'resource_typemapper'))
            return self._get_order_string_recursive(
                identifiers_prefix + [identifiers[0]], identifiers[1:],
                next_model, next_resource, request, order_fields_rfs[current_identifier].subfieldset
            )
        elif model_method and not identifiers_suffix:
            return self._get_order_string_from_method(
                model_method, identifiers_prefix, identifiers, model, resource, request, order_fields_rfs
            )
Example #9
0
 def get_q(self, filter, value, operator_slug, request):
     filter_term = {}
     value = filter.clean_value(value, operator_slug, request)
     for attr in filter.get_suffixes():
         date_val = getattr(value, attr)
         if date_val:
             filter_term[LOOKUP_SEP.join((filter.get_full_filter_key(), attr))] = date_val
     return Q(**filter_term)
Example #10
0
 def get_q(self, filter, value, operator_slug, request):
     filter_term = {}
     value = filter.clean_value(value, operator_slug, request)
     for attr in filter.get_suffixes():
         date_val = getattr(value, attr)
         if date_val:
             filter_term[LOOKUP_SEP.join(
                 (filter.get_full_filter_key(), attr))] = date_val
     return Q(**filter_term)
Example #11
0
 def _update_q_with_prefix(self, q):
     """
     Because implementation of custom filter should be as simple as possible this methods add identifier prefixes
     to the Q objects.
     """
     if isinstance(q, Q):
         q.children = [self._update_q_with_prefix(child) for child in q.children]
         return q
     else:
         return (
             LOOKUP_SEP.join((filter_part for filter_part in self.identifiers_prefix + [q[0]] if filter_part)), q[1]
         )
Example #12
0
    def _add(self, key_path):
        if not self._tree_contains(key_path):
            current = self.root
            for key in key_path:
                current[key] = current.get(key, {})
                prev = current
                current = current[key]

            if current:
                self._remove_childs(key_path, current)

            prev[key] = {}
            self.fieldset[LOOKUP_SEP.join(key_path)] = None
Example #13
0
    def _add(self, key_path):
        if not self._tree_contains(key_path):
            current = self.root
            for key in key_path:
                current[key] = current.get(key, {})
                prev = current
                current = current[key]

            if current:
                self._remove_childs(key_path, current)

            prev[key] = {}
            self.fieldset[LOOKUP_SEP.join(key_path)] = None
Example #14
0
 def _update_q_with_prefix(self, q):
     """
     Because implementation of custom filter should be as simple as possible this methods add identifier prefixes
     to the Q objects.
     """
     if isinstance(q, Q):
         q.children = [
             self._update_q_with_prefix(child) for child in q.children
         ]
         return q
     else:
         return (LOOKUP_SEP.join(
             (filter_part
              for filter_part in self.identifiers_prefix + [q[0]]
              if filter_part)), q[1])
Example #15
0
    def get_q(self, filter, values, operator_slug, request):
        if not isinstance(values, list):
            raise FilterValueError(ugettext('Value must be list'))
        else:
            values = self._clean_list_values(filter, operator_slug, request, values)

        qs_obj_with_all_values = filter.field.model.objects.all()
        for v in set(values):
            qs_obj_with_all_values = qs_obj_with_all_values.filter(**{filter.identifiers[-1]: v})
        return Q(
            **{
                '{}__in'.format(
                    LOOKUP_SEP.join(filter.identifiers[:-1] + ['pk'])
                ): qs_obj_with_all_values.values('pk')
            }
        )
Example #16
0
 def _get_order_string_from_resource(self, identifiers_prefix, identifiers, model, resource, request,
                                     order_fields_rfs):
     """
     :param identifiers_prefix: because order strings are recursive if model relations property contains list of
            identifiers that was used for recursive searching the order string.
     :param identifiers: list of identifiers that conclusively identifies order string.
     :param model: django model class.
     :param resource: resource object.
     :param request: django HTTP request.
     :param order_fields_rfs: RFS of fields that is allowed to order.
     :return: db order method string that is obtained from resource object.
     """
     full_identifiers_string = LOOKUP_SEP.join(identifiers)
     resource_method = get_method_or_none(resource, full_identifiers_string)
     if full_identifiers_string in order_fields_rfs and resource_method:
         return self._get_order_string_from_method(resource_method, identifiers_prefix, identifiers, model,
                                                   resource, request, order_fields_rfs)
Example #17
0
    def get_q(self, filter, values, operator_slug, request):
        if not isinstance(values, list):
            raise FilterValueError(ugettext('Value must be list'))
        else:
            values = self._clean_list_values(filter, operator_slug, request,
                                             values)

        qs_obj_with_all_values = filter.field.model.objects.all()
        for v in set(values):
            qs_obj_with_all_values = qs_obj_with_all_values.filter(
                **{filter.identifiers[-1]: v})
        return Q(
            **{
                '{}__in'.format(
                    LOOKUP_SEP.join(filter.identifiers[:-1] + ['pk'])):
                qs_obj_with_all_values.values('pk')
            })
Example #18
0
 def _get_order_string_from_resource(self, identifiers_prefix, identifiers, model, resource, request,
                                     order_fields_rfs):
     """
     :param identifiers_prefix: because order strings are recursive if model relations property contains list of
            identifiers that was used for recursive searching the order string.
     :param identifiers: list of identifiers that conclusively identifies order string.
     :param model: django model class.
     :param resource: resource object.
     :param request: django HTTP request.
     :param order_fields_rfs: RFS of fields that is allowed to order.
     :return: db order method string that is obtained from resource object.
     """
     full_identifiers_string = LOOKUP_SEP.join(identifiers)
     resource_method = get_method_or_none(resource, full_identifiers_string)
     if full_identifiers_string in order_fields_rfs and resource_method:
         return self._get_order_string_from_method(resource_method, identifiers_prefix, identifiers, model,
                                                   resource, request, order_fields_rfs)
Example #19
0
    def _get_model_filter(self, identifiers_prefix, identifiers, model,
                          resource, request, filters_fields_rfs):
        """
        :param identifiers_prefix: because filters are recursive if model relations property contains list of
               identifiers that was used for recursive searching the filter.
        :param identifiers: list of identifiers that conclusively identifies the filter.
        :param model: django model class.
        :param resource: resource object.
        :param request: django HTTP request.
        :param filters_fields_rfs: RFS of fields that is allowed to filter.
        :return: method returns filter from model fields or methods
        """
        current_identifier = identifiers[0]
        identifiers_suffix = identifiers[1:]

        if current_identifier not in filters_fields_rfs:
            raise FilterIdentifierError

        suffix = LOOKUP_SEP.join(identifiers_suffix)

        model_field = get_field_or_none(model, current_identifier)
        model_method = get_method_or_none(model, current_identifier)

        if model_field and model_field.filter and (
                not suffix or suffix in model_field.filter.get_suffixes()):
            return model_field.filter(identifiers_prefix, [current_identifier],
                                      identifiers_suffix,
                                      field=model_field)
        elif model_field and model_field.is_relation and model_field.related_model:
            # recursive search for filter via related model fields
            next_model = model_field.related_model
            next_resource = get_resource_or_none(
                request, next_model, getattr(resource, 'resource_typemapper'))
            return self._get_filter_recursive(
                identifiers_prefix + [identifiers[0]], identifiers[1:],
                next_model, next_resource, request,
                filters_fields_rfs[current_identifier].subfieldset)
        elif model_method:
            return self._get_method_filter(model_method, identifiers_prefix,
                                           [current_identifier],
                                           identifiers_suffix, model, resource,
                                           request, filters_fields_rfs)
Example #20
0
    def _recursive_generator(self, fields, fields_string, model=None, key_path=None, label_path=None,
                             extended_fieldset=None):
        key_path = key_path or []
        label_path = label_path or []

        allowed_fieldset = self._get_allowed_fieldset()
        if extended_fieldset:
            allowed_fieldset.join(extended_fieldset)

        parsed_fields = [
            (field_name, subfields_string) for field_name, subfields_string in self._parse_fields_string(fields_string)
            if field_name in allowed_fieldset or self.direct_serialization
        ]

        for field_name, subfields_string in parsed_fields:
            self._recursive_generator(
                fields, subfields_string, get_model_from_relation_or_none(model, field_name) if model else None,
                key_path + [field_name],
                label_path + [self._get_label(field_name, model)],
                extended_fieldset=allowed_fieldset[field_name].subfieldset if allowed_fieldset[field_name] else None
            )
        if not parsed_fields:
            label = self.resource.get_field_labels().get(LOOKUP_SEP.join(key_path)) if self.resource else None
            fields.append(Field(key_path, [label] if label else label_path))
Example #21
0
 def _remove_childs(self, key_path, tree):
     if not tree:
         del self.fieldset[LOOKUP_SEP.join(key_path)]
     else:
         for key, subtree in tree.items():
             self._remove_childs(key_path + [key], subtree)
Example #22
0
 def _remove_childs(self, key_path, tree):
     if not tree:
         del self.fieldset[LOOKUP_SEP.join(key_path)]
     else:
         for key, subtree in tree.items():
             self._remove_childs(key_path + [key], subtree)
Example #23
0
 def get_full_filter_key(self):
     return LOOKUP_SEP.join(self.full_identifiers)
Example #24
0
 def _get_order_string(self):
     return LOOKUP_SEP.join(self.identifiers)
Example #25
0
 def _get_order_string(self):
     return LOOKUP_SEP.join(chain(('extra_order', ), self.identifiers))
Example #26
0
 def _get_order_string(self):
     return LOOKUP_SEP.join(self.identifiers)
Example #27
0
 def __hash__(self):
     return hash(LOOKUP_SEP.join(self.key_path))
Example #28
0
 def __hash__(self):
     return hash(LOOKUP_SEP.join(self.key_path))
Example #29
0
 def _get_order_string(self):
     return LOOKUP_SEP.join(chain(('extra_order',), self.identifiers))
Example #30
0
 def get_full_filter_key(self):
     return LOOKUP_SEP.join(self.full_identifiers)