def get_index_values(self, model_instance): filters = tuple([f[0].split(' ')[0] for f in get_filters(*self.filters)]) values = {} for property in set(self.properties + self.integrate + filters): instance = getattr(model_instance.__class__, property) if isinstance(instance, db.ReferenceProperty): value = instance.get_value_for_datastore(model_instance) else: value = getattr(model_instance, property) if property == self.properties[0] and \ isinstance(value, (list, tuple)): value = sorted(value) values[property] = value return values
def should_index(self, values): # Check if filter doesn't match for filter, value in get_filters(*self.filters): attr, op = filter.split(' ') op = op.lower() if (op == '=' and values[attr] != value or op == '!=' and values[attr] == value or op == 'in' and values[attr] not in value or op == '<' and values[attr] >= value or op == '<=' and values[attr] > value or op == '>' and values[attr] <= value or op == '>=' and values[attr] < value): return False elif op not in ('=', '!=', 'in', '<', '<=', '>=', '>'): raise ValueError('Invalid search index filter: %s %s' % (filter, value)) return True
def generate_index_key_names(self, values): if self.filters and not self.should_index(values): return [] # Remove unneeded values filters = tuple([f[0].split(' ')[0] for f in get_filters(*self.filters)]) for filter in filters: if filter not in (self.properties + self.integrate): del values[filter] key_names = [] property_values = values[self.properties[0]] if not isinstance(property_values, (list, tuple)): property_values = (property_values,) for property_value in property_values: parts = [] for property in sorted(values.keys()): if property == self.properties[0]: parts.extend((property, unicode(property_value))) else: parts.extend((property, unicode(values[property]))) key_names.append((property_value, generate_key_name(*parts))) return key_names
def make_paginated_filter(filters=(), order=(), bookmark=None, descending=False, debug=False): # Get bookmark (marks last result entry which we can restart from). # The bookmark is a dictionary containing the values of the previous # page's last item. if order and not isinstance(order, (tuple, list)): order = (order,) order = list(order) filters = get_filters(*filters) inequality = [filter for filter in filters if filter[0].strip().endswith(('!=', '>', '<', '>=', '<='))] if inequality and not order: order.append(inequality[0][0].split(' ')[0]) if '__key__' not in order and '-__key__' not in order: order.append(descending and bookmark is not None and '-__key__' or '__key__') if bookmark is None: return [(filters, order)] # Assert that all of the properties in the query are also in the bookmark. # We check sort order below. for filter in inequality: if filter[0].split(' ')[0] not in bookmark: raise ValueError('Property for filter %r not in bookmark!' % (filter,)) if '__key__' not in bookmark: raise ValueError('__key__ not in bookmark!') # Prepare the original query as a template for the derived queries for filter in inequality: filters.remove(filter) for property in order: property = property.lstrip('-') if property == '__key__': continue if property not in bookmark: raise ValueError('Sort order property %s not in bookmark!' % property) filters.append((property + ' =', bookmark[property])) # order_backup gets used in for loop below order_backup = order[:] for index, property in enumerate(order[:]): if property.lstrip('-') != '__key__': if descending: if property.startswith('-'): order_backup[index] = property.lstrip('-') else: order_backup[index] = '-' + property order.remove(property) # Generate derived queries queries = [] for property in reversed(order_backup): property_backup = property property = property.lstrip('-') if property != '__key__': filters.remove((property + ' =', bookmark[property])) order.insert(0, property_backup) filters_copy = filters[:] order_copy = order[:] if not property_backup.startswith('-'): op = ' >' else: op = ' <' filters_copy.append((property + op, bookmark[property])) # Add back inequality filter on property for filter in inequality: if filter[0].split(' ')[0] == property and \ filter[0].rstrip(' =') != property + op: filters_copy.append(filter) queries.append((filters_copy, order_copy)) return queries