예제 #1
0
    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
예제 #2
0
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
예제 #3
0
    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
예제 #4
0
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))
예제 #5
0
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
예제 #6
0
    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())}"
            )
예제 #7
0
    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
예제 #8
0
    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
예제 #9
0
    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
예제 #10
0
 def default_name(self):
     raise ParamsError("No obvious default name exists for this annotation")
예제 #11
0
 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)