在 Django 的某个页面上,我想要显示已排序对象列表的子集。相关对象的整个列表非常长,并且在用户查看页面时很有可能发生变化。我不介意页面不是最新的,但我确实需要确保当用户转到下一页时,用户将看到原始排序列表中的下一个 n 个对象。因此,由于数据可能发生变化,使用 Django 的内置分页或 Django-endless-pagination 这类十分出色的库在转到“下一页”时不会返回正确的结果。
为了举例说明我的意思,假设我们有对象 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],并想要从小到大排序后每页显示 5 个对象。第一页将如下所示:
1, 2, 3, 4, 5
但是,在查看此页面时,3 和 4 被删除了。如果我们转到“下一页”,分页将重新查询该集合并返回:
8, 9, 10, 11, 12
我意识到这是分页的预期行为,但我希望找到一种简单的方法来使下一页显示:
6, 7, 8, 9, 10
最显而易见的方法是进行一些客户端分页,我意识到有一个很好的 jQuery 库可以实现此目的,但对象的数量可能太大,以至于这种解决方案无法实现。
有没有一种简单的方法可以在查询集上进行分页,并继续使用原始查询集返回的结果,而不是重新获取可能已更改的查询集?
非常感谢您能为我提供任何见解!
2、解决方案
一种可能的解决方案是创建自己的分页函数,该函数不是将下一个链接指向某个页面,而是可以传递一条记录,该记录是下一页的顶级记录。问题是,这仅适用于要添加/更改的项目只是列表中的第一个项目的情况。
以下是如何创建您自己的分页函数的示例:
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
def custom_pagination(request, queryset, per_page, top_record):
"""
Custom pagination function that uses a top record to determine the next page.
Args:
request: The current request object.
queryset: The queryset to paginate.
per_page: The number of objects to display per page.
top_record: The top record of the next page.
Returns:
A paginator object.
"""
paginator = Paginator(queryset, per_page)
page_number = 1
# Determine the page number based on the top record.
for page in paginator.page_range:
if page.object_list[0] == top_record:
page_number = page.number
break
# Get the current page.
try:
page = paginator.page(page_number)
except (EmptyPage, PageNotAnInteger):
page = paginator.page(1)
# Return the paginator object.
return paginator, page
您可以在视图中使用此自定义分页函数如下所示:
from django.shortcuts import render
def my_view(request):
"""
A view that uses the custom pagination function.
Args:
request: The current request object.
Returns:
An HTTP response.
"""
# Get the queryset to paginate.
queryset = MyModel.objects.all()
# Get the top record of the next page.
top_record = request.GET.get('top_record', None)
# Create the paginator object.
paginator, page = custom_pagination(request, queryset, 5, top_record)
# Render the template.
return render(request, 'my_template.html', {'paginator': paginator, 'page': page})
这将允许您在不断变化的数据集上实现分页,而无需担心重新获取查询集。