fix everything?

This commit is contained in:
collerek
2021-03-07 17:48:26 +01:00
parent f85fa7b8a7
commit d388b9f745
5 changed files with 61 additions and 51 deletions

View File

@ -46,9 +46,16 @@ class OrderAction(QueryAction):
prefix = f"{self.table_prefix}_" if self.table_prefix else "" prefix = f"{self.table_prefix}_" if self.table_prefix else ""
return f"{prefix}{self.table}" f".{self.field_alias}" return f"{prefix}{self.table}" f".{self.field_alias}"
def get_min_or_max(self): def get_min_or_max(self) -> sqlalchemy.sql.expression.TextClause:
"""
Used in limit sub queries where you need to use aggregated functions
in order to order by columns not included in group by.
:return: min or max function to order
:rtype: sqlalchemy.sql.elements.TextClause
"""
prefix = f"{self.table_prefix}_" if self.table_prefix else "" prefix = f"{self.table_prefix}_" if self.table_prefix else ""
if self.direction == '': if self.direction == "":
return text(f"min({prefix}{self.table}" f".{self.field_alias})") return text(f"min({prefix}{self.table}" f".{self.field_alias})")
else: else:
return text(f"max({prefix}{self.table}" f".{self.field_alias}) desc") return text(f"max({prefix}{self.table}" f".{self.field_alias}) desc")

View File

@ -153,9 +153,10 @@ class Query:
return expr return expr
def _build_pagination_condition( def _build_pagination_condition(
self self,
) -> Tuple[ ) -> Tuple[
sqlalchemy.sql.expression.TextClause, sqlalchemy.sql.expression.TextClause]: sqlalchemy.sql.expression.TextClause, sqlalchemy.sql.expression.TextClause
]:
""" """
In order to apply limit and offset on main table in join only In order to apply limit and offset on main table in join only
(otherwise you can get only partially constructed main model (otherwise you can get only partially constructed main model
@ -183,10 +184,9 @@ class Query:
limit_qry = sqlalchemy.sql.select([qry_text]) limit_qry = sqlalchemy.sql.select([qry_text])
limit_qry = limit_qry.select_from(self.select_from) limit_qry = limit_qry.select_from(self.select_from)
limit_qry = FilterQuery(filter_clauses=self.filter_clauses).apply(limit_qry) limit_qry = FilterQuery(filter_clauses=self.filter_clauses).apply(limit_qry)
limit_qry = FilterQuery(filter_clauses=self.exclude_clauses, limit_qry = FilterQuery(
exclude=True).apply( filter_clauses=self.exclude_clauses, exclude=True
limit_qry ).apply(limit_qry)
)
limit_qry = limit_qry.group_by(qry_text) limit_qry = limit_qry.group_by(qry_text)
for order_by in maxes.values(): for order_by in maxes.values():
limit_qry = limit_qry.order_by(order_by) limit_qry = limit_qry.order_by(order_by)
@ -194,7 +194,8 @@ class Query:
limit_qry = OffsetQuery(query_offset=self.query_offset).apply(limit_qry) limit_qry = OffsetQuery(query_offset=self.query_offset).apply(limit_qry)
limit_qry = limit_qry.alias("limit_query") limit_qry = limit_qry.alias("limit_query")
on_clause = sqlalchemy.text( on_clause = sqlalchemy.text(
f"limit_query.{pk_alias}={self.table.name}.{pk_alias}") f"limit_query.{pk_alias}={self.table.name}.{pk_alias}"
)
return limit_qry, on_clause return limit_qry, on_clause
def _apply_expression_modifiers( def _apply_expression_modifiers(

View File

@ -281,7 +281,7 @@ class QuerySet:
limit_raw_sql=self.limit_sql_raw, limit_raw_sql=self.limit_sql_raw,
) )
exp = qry.build_select_expression() exp = qry.build_select_expression()
print("\n", exp.compile(compile_kwargs={"literal_binds": True})) # print("\n", exp.compile(compile_kwargs={"literal_binds": True}))
return exp return exp
def filter( # noqa: A003 def filter( # noqa: A003

View File

@ -153,8 +153,7 @@ async def test_or_filters():
assert books[0].title == "The Witcher" assert books[0].title == "The Witcher"
with pytest.raises(QueryDefinitionError): with pytest.raises(QueryDefinitionError):
await Book.objects.select_related("author").filter('wrong').all() await Book.objects.select_related("author").filter("wrong").all()
# TODO: Check / modify # TODO: Check / modify

View File

@ -221,12 +221,15 @@ async def test_sort_order_on_related_model():
assert owners[1].toys[1].name == "Toy 5" assert owners[1].toys[1].name == "Toy 5"
assert owners[1].name == "Hermes" assert owners[1].name == "Hermes"
toys = await Toy.objects.select_related('owner').order_by( toys = (
['owner__name', 'name']).limit( await Toy.objects.select_related("owner")
2).all() .order_by(["owner__name", "name"])
.limit(2)
.all()
)
assert len(toys) == 2 assert len(toys) == 2
assert toys[0].name == 'Toy 2' assert toys[0].name == "Toy 2"
assert toys[1].name == 'Toy 3' assert toys[1].name == "Toy 3"
@pytest.mark.asyncio @pytest.mark.asyncio