1
1
from __future__ import annotations
2
2
3
3
import types
4
- from collections .abc import AsyncIterator , Callable , Generator , Iterable
4
+ from collections .abc import AsyncIterator , Callable , Collection , Generator , Iterable
5
5
from copy import copy
6
6
from typing import TYPE_CHECKING , Any , Generic , Optional , TypeVar , cast , overload
7
7
8
8
from pypika_tortoise import JoinType , Order , Table
9
9
from pypika_tortoise .analytics import Count
10
10
from pypika_tortoise .functions import Cast
11
11
from pypika_tortoise .queries import QueryBuilder
12
- from pypika_tortoise .terms import Case , Field , Star , Term , ValueWrapper
12
+ from pypika_tortoise .terms import Case , Field , Star , Term , ValueWrapper , PseudoColumn
13
13
from typing_extensions import Literal , Protocol
14
14
15
15
from tortoise .backends .base .client import BaseDBAsyncClient , Capabilities
@@ -179,7 +179,8 @@ def resolve_ordering(
179
179
model : type [Model ],
180
180
table : Table ,
181
181
orderings : Iterable [tuple [str , str | Order ]],
182
- annotations : dict [str , Any ],
182
+ annotations : dict [str , Term | Expression ],
183
+ fields_for_select : Collection [str ] | None = None ,
183
184
) -> None :
184
185
"""
185
186
Applies standard ordering to QuerySet.
@@ -189,6 +190,8 @@ def resolve_ordering(
189
190
(to allow self referential joins)
190
191
:param orderings: What columns/order to order by
191
192
:param annotations: Annotations that may be ordered on
193
+ :param fields_for_select: Contains fields that are selected in the SELECT clause if
194
+ .only(), .values() or .values_list() are used.
192
195
193
196
:raises FieldError: If a field provided does not exist in model.
194
197
"""
@@ -214,18 +217,27 @@ def resolve_ordering(
214
217
{},
215
218
)
216
219
elif field_name in annotations :
217
- if isinstance (annotation := annotations [field_name ], Term ):
218
- term : Term = annotation
220
+ term : Term
221
+ if not fields_for_select or field_name in fields_for_select :
222
+ # The annotation is SELECTed, we can just reference it in the following cases:
223
+ # - Empty fields_for_select means that all columns and annotations are selected,
224
+ # hence we can reference the annotation.
225
+ # - The annotation is in fields_for_select, hence we can reference it.
226
+ term = PseudoColumn (field_name )
219
227
else :
220
- annotation_info = annotation .resolve (
221
- ResolveContext (
222
- model = self .model ,
223
- table = table ,
224
- annotations = annotations ,
225
- custom_filters = {},
226
- )
227
- )
228
- term = annotation_info .term
228
+ # The annotation is not in SELECT, resolve it
229
+ annotation = annotations [field_name ]
230
+ if isinstance (annotation , Term ):
231
+ term = annotation
232
+ else :
233
+ term = annotation .resolve (
234
+ ResolveContext (
235
+ model = self .model ,
236
+ table = table ,
237
+ annotations = annotations ,
238
+ custom_filters = {},
239
+ )
240
+ ).term
229
241
self .query = self .query .orderby (term , order = ordering [1 ])
230
242
else :
231
243
field_object = model ._meta .fields_map .get (field_name )
@@ -1078,7 +1090,11 @@ def _make_query(self) -> None:
1078
1090
if append_item not in self ._select_related_idx :
1079
1091
self ._select_related_idx .append (append_item )
1080
1092
self .resolve_ordering (
1081
- self .model , self .model ._meta .basetable , self ._orderings , self ._annotations
1093
+ self .model ,
1094
+ self .model ._meta .basetable ,
1095
+ self ._orderings ,
1096
+ self ._annotations ,
1097
+ self ._fields_for_select ,
1082
1098
)
1083
1099
self .resolve_filters ()
1084
1100
if self ._limit is not None :
@@ -1562,6 +1578,7 @@ def _make_query(self) -> None:
1562
1578
table = self .model ._meta .basetable ,
1563
1579
orderings = self ._orderings ,
1564
1580
annotations = self ._annotations ,
1581
+ fields_for_select = self ._fields_for_select_list ,
1565
1582
)
1566
1583
self .resolve_filters ()
1567
1584
if self ._limit :
@@ -1683,6 +1700,7 @@ def _make_query(self) -> None:
1683
1700
table = self .model ._meta .basetable ,
1684
1701
orderings = self ._orderings ,
1685
1702
annotations = self ._annotations ,
1703
+ fields_for_select = self ._fields_for_select .keys (),
1686
1704
)
1687
1705
self .resolve_filters ()
1688
1706
0 commit comments