У меня есть приложение Django для конкурсов, где конкурс может иметь несколько записей -
Contest
в models.py
class Contest(models.Model):
is_winners_announced = models.BooleanField(default=False)
...
ContestEntry
в models.py
class ContestEntry(models.Model):
contest = models.ForeignKey(Contest, on_delete=models.CASCADE,
related_name='entries')
submitted_at = models.DateTimeField(auto_now_add=True)
assigned_rank = models.PositiveSmallIntegerField(null=True, blank=True)
...
В ContestViewSet у меня есть маршрут detail
, который обслуживает все записи для конкурса -
def pagination_type_by_field(PaginationClass, field):
class CustomPaginationClass(PaginationClass):
ordering = field
return CustomPaginationClass
...
@decorators.action(
detail=True,
methods=['GET'],
)
def entries(self, request, pk=None):
contest = self.get_object()
entries = contest.entries.all()
# Order by rank only if winners are announced
ordering_array = ['-submitted_at']
if contest.is_winners_announced:
ordering_array.insert(0, 'assigned_rank')
pagination_obj = pagination_type_by_field(
pagination.CursorPagination, ordering_array)()
paginated_data = contest_serializers.ContestEntrySerializer(
instance=pagination_obj.paginate_queryset(entries, request),
many=True,
context={'request': request},
).data
return pagination_obj.get_paginated_response(paginated_data)
Разбиение на страницы отлично работает, когда победители не объявлены для конкурса -
GET http://localhost:8000/contests/<id>/entries/
{
"next": "http://localhost:8000/contests/<id>/entries/?cursor=cD0yMDIwLTAyLTE3KzIwJTNBNDQlM0EwNy4yMDMyMTUlMkIwMCUzQTAw",
"previous": null,
"results": [ // Contains all objects and pagination works
{...},
...
]
}
Но когда объявлены победители, разбиение на страницы разбивается:
GET http://localhost:8000/contests/<id>/entries/
{
"next": "https://localhost:8000/contests/4/entries/?cursor=bz03JnA9Mw%3D%3D",
"previous": null,
"results": [ // Contains all objects only for the first page; next page is empty even when there are more entries pending to be displayed
{...},
...
]
}
Странная вещь, которую я вижу здесь, это то, что курсор в Второй случай выглядит иначе, чем обычно.