mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-08-01 11:00:13 +03:00
Fix CursorPagination when objects get deleted between calls (#6504)
Co-Authored-By: Tom Quinonero <tq@3yourmind.com>
This commit is contained in:
parent
fab3a9c8b3
commit
1cd4f9fec1
|
@ -589,7 +589,7 @@ class CursorPagination(BasePagination):
|
||||||
if not self.has_next:
|
if not self.has_next:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if self.cursor and self.cursor.reverse and self.cursor.offset != 0:
|
if self.page and self.cursor and self.cursor.reverse and self.cursor.offset != 0:
|
||||||
# If we're reversing direction and we have an offset cursor
|
# If we're reversing direction and we have an offset cursor
|
||||||
# then we cannot use the first position we find as a marker.
|
# then we cannot use the first position we find as a marker.
|
||||||
compare = self._get_position_from_instance(self.page[-1], self.ordering)
|
compare = self._get_position_from_instance(self.page[-1], self.ordering)
|
||||||
|
@ -597,12 +597,14 @@ class CursorPagination(BasePagination):
|
||||||
compare = self.next_position
|
compare = self.next_position
|
||||||
offset = 0
|
offset = 0
|
||||||
|
|
||||||
|
has_item_with_unique_position = False
|
||||||
for item in reversed(self.page):
|
for item in reversed(self.page):
|
||||||
position = self._get_position_from_instance(item, self.ordering)
|
position = self._get_position_from_instance(item, self.ordering)
|
||||||
if position != compare:
|
if position != compare:
|
||||||
# The item in this position and the item following it
|
# The item in this position and the item following it
|
||||||
# have different positions. We can use this position as
|
# have different positions. We can use this position as
|
||||||
# our marker.
|
# our marker.
|
||||||
|
has_item_with_unique_position = True
|
||||||
break
|
break
|
||||||
|
|
||||||
# The item in this position has the same position as the item
|
# The item in this position has the same position as the item
|
||||||
|
@ -611,7 +613,7 @@ class CursorPagination(BasePagination):
|
||||||
compare = position
|
compare = position
|
||||||
offset += 1
|
offset += 1
|
||||||
|
|
||||||
else:
|
if self.page and not has_item_with_unique_position:
|
||||||
# There were no unique positions in the page.
|
# There were no unique positions in the page.
|
||||||
if not self.has_previous:
|
if not self.has_previous:
|
||||||
# We are on the first page.
|
# We are on the first page.
|
||||||
|
@ -630,6 +632,9 @@ class CursorPagination(BasePagination):
|
||||||
offset = self.cursor.offset + self.page_size
|
offset = self.cursor.offset + self.page_size
|
||||||
position = self.previous_position
|
position = self.previous_position
|
||||||
|
|
||||||
|
if not self.page:
|
||||||
|
position = self.next_position
|
||||||
|
|
||||||
cursor = Cursor(offset=offset, reverse=False, position=position)
|
cursor = Cursor(offset=offset, reverse=False, position=position)
|
||||||
return self.encode_cursor(cursor)
|
return self.encode_cursor(cursor)
|
||||||
|
|
||||||
|
@ -637,7 +642,7 @@ class CursorPagination(BasePagination):
|
||||||
if not self.has_previous:
|
if not self.has_previous:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if self.cursor and not self.cursor.reverse and self.cursor.offset != 0:
|
if self.page and self.cursor and not self.cursor.reverse and self.cursor.offset != 0:
|
||||||
# If we're reversing direction and we have an offset cursor
|
# If we're reversing direction and we have an offset cursor
|
||||||
# then we cannot use the first position we find as a marker.
|
# then we cannot use the first position we find as a marker.
|
||||||
compare = self._get_position_from_instance(self.page[0], self.ordering)
|
compare = self._get_position_from_instance(self.page[0], self.ordering)
|
||||||
|
@ -645,12 +650,14 @@ class CursorPagination(BasePagination):
|
||||||
compare = self.previous_position
|
compare = self.previous_position
|
||||||
offset = 0
|
offset = 0
|
||||||
|
|
||||||
|
has_item_with_unique_position = False
|
||||||
for item in self.page:
|
for item in self.page:
|
||||||
position = self._get_position_from_instance(item, self.ordering)
|
position = self._get_position_from_instance(item, self.ordering)
|
||||||
if position != compare:
|
if position != compare:
|
||||||
# The item in this position and the item following it
|
# The item in this position and the item following it
|
||||||
# have different positions. We can use this position as
|
# have different positions. We can use this position as
|
||||||
# our marker.
|
# our marker.
|
||||||
|
has_item_with_unique_position = True
|
||||||
break
|
break
|
||||||
|
|
||||||
# The item in this position has the same position as the item
|
# The item in this position has the same position as the item
|
||||||
|
@ -659,7 +666,7 @@ class CursorPagination(BasePagination):
|
||||||
compare = position
|
compare = position
|
||||||
offset += 1
|
offset += 1
|
||||||
|
|
||||||
else:
|
if self.page and not has_item_with_unique_position:
|
||||||
# There were no unique positions in the page.
|
# There were no unique positions in the page.
|
||||||
if not self.has_next:
|
if not self.has_next:
|
||||||
# We are on the final page.
|
# We are on the final page.
|
||||||
|
@ -678,6 +685,9 @@ class CursorPagination(BasePagination):
|
||||||
offset = 0
|
offset = 0
|
||||||
position = self.next_position
|
position = self.next_position
|
||||||
|
|
||||||
|
if not self.page:
|
||||||
|
position = self.previous_position
|
||||||
|
|
||||||
cursor = Cursor(offset=offset, reverse=True, position=position)
|
cursor = Cursor(offset=offset, reverse=True, position=position)
|
||||||
return self.encode_cursor(cursor)
|
return self.encode_cursor(cursor)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user