Skip to content

Commit be1df65

Browse files
Daan van der Kallendaanvdk
authored andcommitted
Fix after filter when ordering on annotations
1 parent 3388534 commit be1df65

File tree

1 file changed

+29
-9
lines changed

1 file changed

+29
-9
lines changed

binder/views.py

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1543,20 +1543,31 @@ def _apply_q_with_possible_annotations(self, queryset, q, annotations):
15431543
return queryset.filter(q)
15441544

15451545

1546-
def _after_expr(self, request, after_id):
1546+
def _after_expr(self, request, after_id, include_annotations):
15471547
"""
15481548
This method given a request and an id returns a boolean expression that
15491549
indicates if a record would show up after the provided id for the
15501550
ordering specified by this request.
15511551
"""
1552-
# First we get the object we need to use as our base for our filter
1552+
queryset = self.get_queryset(request)
1553+
annotations = {
1554+
name: value['expr']
1555+
for name, value in self.annotations(request, include_annotations).items()
1556+
}
1557+
1558+
# We do an order by on a copy of annotations so that we see which keys
1559+
# it pops
1560+
annotations_copy = annotations.copy()
1561+
ordering = self._order_by_base(queryset, request, annotations_copy).query.order_by
1562+
required_annotations = set(annotations) - set(annotations_copy)
1563+
1564+
queryset = queryset.annotate(**{name: annotations[name] for name in required_annotations})
15531565
try:
1554-
obj = self.get_queryset(request).get(pk=int(after_id))
1566+
obj = queryset.get(pk=int(after_id))
15551567
except (ValueError, self.model.DoesNotExist):
15561568
raise BinderRequestError(f'invalid value for after_id: {after_id!r}')
15571569

15581570
# Now we will build up a comparison expr based on the order by
1559-
ordering = self.order_by(self.model.objects.all(), request).query.order_by
15601571
left_exprs = []
15611572
right_exprs = []
15621573

@@ -1587,9 +1598,11 @@ def _after_expr(self, request, after_id):
15871598

15881599
# Now we turn this into one big comparison
15891600
if len(ordering) == 1:
1590-
return GreaterThan(left_exprs[0], right_exprs[0])
1601+
expr = GreaterThan(left_exprs[0], right_exprs[0])
15911602
else:
1592-
return GreaterThan(Tuple(*left_exprs), Tuple(*right_exprs))
1603+
expr = GreaterThan(Tuple(*left_exprs), Tuple(*right_exprs))
1604+
1605+
return expr, required_annotations
15931606

15941607

15951608
def _get_filtered_queryset_base(self, request, pk=None, include_annotations=None):
@@ -1611,7 +1624,7 @@ def _get_filtered_queryset_base(self, request, pk=None, include_annotations=None
16111624

16121625
annotations = {
16131626
name: value['expr']
1614-
for name, value in get_annotations(queryset.model, request, include_annotations.get('')).items()
1627+
for name, value in self.annotations(request, include_annotations).items()
16151628
}
16161629

16171630
#### filters
@@ -1635,8 +1648,15 @@ def _get_filtered_queryset_base(self, request, pk=None, include_annotations=None
16351648
except KeyError:
16361649
pass
16371650
else:
1638-
expr = self._after_expr(request, after)
1639-
queryset = queryset.filter(expr)
1651+
after_expr, required_annotations = self._after_expr(request, after, include_annotations)
1652+
for name in required_annotations:
1653+
try:
1654+
expr = annotations.pop(name)
1655+
except KeyError:
1656+
pass
1657+
else:
1658+
queryset = queryset.annotate(**{name: expr})
1659+
queryset = queryset.filter(after_expr)
16401660

16411661
return queryset, annotations
16421662

0 commit comments

Comments
 (0)