From daff03290697e7b762813e83f158548e611ad816 Mon Sep 17 00:00:00 2001 From: Daan van der Kallen Date: Thu, 23 May 2024 16:50:06 +0200 Subject: [PATCH] Fix after filter when ordering on annotations --- binder/views.py | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/binder/views.py b/binder/views.py index b8166326..4f2926af 100644 --- a/binder/views.py +++ b/binder/views.py @@ -1543,20 +1543,35 @@ def _apply_q_with_possible_annotations(self, queryset, q, annotations): return queryset.filter(q) - def _after_expr(self, request, after_id): + def _after_expr(self, request, after_id, include_annotations): """ This method given a request and an id returns a boolean expression that indicates if a record would show up after the provided id for the ordering specified by this request. """ - # First we get the object we need to use as our base for our filter + queryset = self.get_queryset(request) + annotations = { + name: value['expr'] + for name, value in self.annotations(request, include_annotations).items() + } + + # We do an order by on a copy of annotations so that we see which keys + # it pops + annotations_copy = annotations.copy() + ordering = self._order_by_base(queryset, request, annotations).query.order_by + + queryset = queryset.annotate(**{ + name: expr + for name, expr in annotations.items() + if name not in annotations_copy + }) + try: - obj = self.get_queryset(request).get(pk=int(after_id)) + obj = queryset.get(pk=int(after_id)) except (ValueError, self.model.DoesNotExist): raise BinderRequestError(f'invalid value for after_id: {after_id!r}') # Now we will build up a comparison expr based on the order by - ordering = self.order_by(self.model.objects.all(), request).query.order_by left_exprs = [] right_exprs = [] @@ -1611,7 +1626,7 @@ def _get_filtered_queryset_base(self, request, pk=None, include_annotations=None annotations = { name: value['expr'] - for name, value in get_annotations(queryset.model, request, include_annotations.get('')).items() + for name, value in self.annotations(request, include_annotations).items() } #### filters @@ -1635,7 +1650,7 @@ def _get_filtered_queryset_base(self, request, pk=None, include_annotations=None except KeyError: pass else: - expr = self._after_expr(request, after) + expr = self._after_expr(request, after, include_annotations) queryset = queryset.filter(expr) return queryset, annotations