def annotate(self, *args, **kwargs) -> "QuerySet[MODEL]": """ Annotate result with aggregation or function result. """ for annotation in itertools.chain(args, kwargs.values()): if not isinstance(annotation, (Term, Annotation)): raise TypeError("{} is expected to be instance of Annotation or pypika.terms.Term".format(annotation)) args = [TermAnnotation(t) if isinstance(t, Term) else t for t in args] kwargs = {k: TermAnnotation(v) if isinstance(v, Term) else v for k, v in kwargs.items()} args_dict = {arg.default_name(): arg for arg in args} duplicate_keys = args_dict.keys() & kwargs.keys() if duplicate_keys: raise ParamsError("Duplicate annotations: {}".format(duplicate_keys)) args_dict.update(kwargs) duplicate_keys = args_dict.keys() & self.annotations if duplicate_keys: raise ParamsError("Duplicate annotations: {}".format(duplicate_keys)) duplicate_keys = args_dict.keys() & self.model._meta.fields_map.keys() if duplicate_keys: raise ParamsError("Annotations {} conflict with existing model fields".format(duplicate_keys)) queryset = self._clone() queryset.annotations.update(args_dict) return queryset
def _get_connection(connection_name: Optional[str]) -> BaseDBAsyncClient: from tortoise import Tortoise if connection_name: connection = Tortoise.get_connection(connection_name) elif len(Tortoise._connections) == 1: connection = list(Tortoise._connections.values())[0] else: raise ParamsError( 'You are running with multiple databases, so you should specify connection_name' ) return connection
def limit(self, limit: int) -> "QuerySet[MODEL]": """ Limits QuerySet to given length. :raises ParamsError: Limit should be non-negative number. """ if limit < 0: raise ParamsError("Limit should be non-negative number") queryset = self._clone() queryset._limit = limit return queryset
def term_name(term: PyPikaTerm) -> str: if isinstance(term, ValueWrapper): return str(term.value) if isinstance(term, ArithmeticExpression): return "{}__{}__{}".format(term_name(term.left), str(term.operator), term_name(term.right)) if isinstance(term, PyPikaFunction): return "{}__{}".format("__".join(map(term_name, term.args)), term.name.lower()) raise ParamsError("Unable to find term name {}".format(term))
def _get_connection(connection_name: Optional[str]) -> "BaseDBAsyncClient": from tortoise import Tortoise if connection_name: connection = current_transaction_map[connection_name].get() elif len(Tortoise._connections) == 1: connection_name = list(Tortoise._connections.keys())[0] connection = current_transaction_map[connection_name].get() else: raise ParamsError( "You are running with multiple databases, so you should specify" f" connection_name: {list(Tortoise._connections.keys())}") return connection
def get_transaction_db_client( self, connection_name: Optional[str]) -> BaseDBAsyncClient: if connection_name: return self._current_transaction_map[connection_name].get() elif len(self._current_transaction_map) == 1: return list(self._current_transaction_map.values())[0].get() else: raise ParamsError( "You are running with multiple databases, so you should specify" f" connection_name: {list(self._current_transaction_map.keys())}" )
def offset(self, offset: int) -> "QuerySet[MODEL]": """ Query offset for QuerySet. :raises ParamsError: Offset should be non-negative number. """ if offset < 0: raise ParamsError("Offset should be non-negative number") queryset = self._clone() queryset._offset = offset if self.capabilities.requires_limit and queryset._limit is None: queryset._limit = 1000000 return queryset
def __parse_orderings(self, *orderings: Union[str, Node]) -> None: parsed_orders: List[QueryOrdering] = [] for ordering in orderings: if isinstance(ordering, Node): parsed_orders.append(QueryOrderingNode(ordering)) elif isinstance(ordering, str): if ordering[0] == "-": field_name = ordering[1:] order_type = Order.desc else: field_name = ordering order_type = Order.asc parsed_orders.append(QueryOrderingField( field_name, order_type)) else: raise ParamsError("Unknown ordering type: {} at {}".format( type(ordering), ordering)) self._orderings = parsed_orders
def clone(self: MODEL, pk: Any = EMPTY) -> MODEL: """ Create a new clone of the object that when you do a ``.save()`` will create a new record. :param pk: An optionally required value if the model doesn't generate its own primary key. Any value you specify here will always be used. :return: A copy of the current object without primary key information. :raises ParamsError: If pk is required but not provided. """ obj = copy(self) if pk is EMPTY: pk_field: Field = self._meta.pk if pk_field.generated is False and pk_field.default is None: raise ParamsError( f"{self._meta.full_name} requires explicit primary key. Please use .clone(pk=<value>)" ) else: obj.pk = None else: obj.pk = pk obj._saved_in_db = False return obj
def default_name(self): raise ParamsError("No obvious default name exists for this annotation")
def default_name(self) -> str: try: return term_name(self._term) except ParamsError as e: raise ParamsError( "No obvious default name exists for this annotation", e)