Source code for lighty.db.query

import operator

from .backend import datastore
from .fields import Field


[docs]class Query(object): '''Query class ''' __slots__ = ('__add__', '__and__', '__call__', '__init__', '__iter__', '__getslice__', '__len__', '__neg__', '__not__', '__or__', 'distinct', 'include', 'exclude', 'fetch', 'from_query', 'values', '_cache', 'dist', '_from_query', 'limit', 'model', 'operation', 'operand', 'order', 'offset', ) def __init__(self, operand=None, operation=operator.__and__, from_query=None, offset=0, limit=None, model=None): '''Create new query in a form from_query operation operand ''' self._cache = None self._from_query = from_query self.operation = operation self.operand = operand self.dist = False self.order = None self.offset = offset self.limit = limit if from_query is not None: self.model = from_query.model self.dist = from_query.dist self.order = from_query.order if from_query.offset > 0: self.offset += from_query.offset if from_query.limit: self.limit = from_query.limit elif operand is not None: self.model = operand.model elif model is not None: self.model = model else: raise AttributeError('Query requires model to be specified') def __and__(self, operand): '''Creates new query from this query with operation AND and specified operand: >>> Query(ModelClass.field > 10) & Query(ModelClass.field < 20) SELECT * FROM modelclass WHERE field > 10 AND field < 20 ''' return Query(operand=operand, operation=operator.__and__, from_query=self) __mul__ = __and__ filter = __and__ where = __and__ def __neg__(self): '''Get query excludes values >>> not Query(ModelClass.field > 0) SELECT * FROM modelclass WHERE NOT (field > 0) ''' return Query(operation=operator.__not__, from_query=self) def __sub__(self, operand): '''Creates new query from this query with operation AND and specified operand: Query(ModelClass.field > 10) & Query(ModelClass.field < 20) equivalent to: SELECT * FROM modelclass WHERE field > 10 AND field < 20 ''' return Query(operand=Query(operator.__not__, operand), operation=operator.__and__, from_query=self) exclude = __sub__ def __or__(self, operand): '''Creates new query from this query with operation OR and specified operand ''' return Query(operand=operand, operation=operator.__or__, from_query=self) __add__ = __or__ include = __or__ def __repr__(self): '''Get string representation includes class name and query string >>> Query(ModelClass.field > 0) <Query: "SELECT * FROM modelclass WHERE field > 0"> ''' return '<Query: "%s">' % self.__str__() def __str__(self): '''Get the query string >>> str(Query(ModelClass.field > 0)) SELECT * FROM modelclass WHERE field > 0 ''' if self._from_query is None: if self.operation == operator.__not__: return '%s (%s)' % (operator.__not__, str(self.operation)) return str(self.operand) return '(%s) %s %s' % (str(self._from_query), self.operation, self.operand)
[docs] def distinct(self): '''Return's a query copy with distinct modifier ''' query = Query(operand=self.operand, operation=self.operation, from_query=self._from_query, model=self.model) query.dist = True return query
[docs] def order_by(self, *args): '''Query ordering ''' for field in args: if not isinstance(field, Field): raise AttributeError('You can sort only by model fields') elif field.model != self.model.__name__: raise AttributeError("%s.%s not from model %s" % (field.name, field.model, self.model.__name__)) query = Query(operand=self.operand, operation=self.operation, from_query=self._from_query, model=self.model) query.order = args return query
def __call__(self): '''Returns the query that copies current query ''' return Query(operand=self.operand, operation=self.operation, from_query=self._from_query, model=self.model)
[docs] def fetch(self, cache=False): '''Fetch the result ''' if cache: self._cache = [item for item in self] return self.__iter__()
[docs] def values(self, fields): '''Return's dictionary of fields for specified model ''' return datastore.query(self, fields)
def __iter__(self): '''Returns and iterator throuch data from datastore ''' if self._cache: for item in self._cache: yield item for item in datastore.query(self): yield self.model(is_new=False, **item) def __len__(self): '''Get number of items in query ''' return len(self._cache) if self._cache else datastore.count(self) def __getslice__(self, i=0, j=None): '''Get the query that contains a slice of current query ''' return Query(from_query=self._from_query, model=self.model, offset=i, limit=j)