我需要进行真正的分页,而不是对所有已检索的数据进行分页。 Django文档站点中的示例就像;
def listing(request):
contact_list = Contacts.objects.all()
paginator = Paginator(contact_list, 25) # Show 25 contacts per page
page = request.GET.get('page')
try:
contacts = paginator.page(page)
except PageNotAnInteger:
# If page is not an integer, deliver first page.
contacts = paginator.page(1)
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
contacts = paginator.page(paginator.num_pages)
return render_to_response('list.html', {"contacts": contacts})
此代码在所有已检索记录上分页记录。但是有一个麻烦。如果记录太多,试图检索所有记录需要花费很多时间。我需要一个解决方案来从数据库中逐页检索记录。
在Django中还有其他解决办法吗?
答案 0 :(得分:18)
你做出了错误的假设。 Django在分页时不检索所有对象:它适当地切割查询集,在SQL上使用LIMIT和COUNT。
答案 1 :(得分:0)
查看Paginator类(django / core / paginator.py),它只获取所需的页面。大表只有一个问题:如果你想显示总页数,你必须在整个表上计数(*),这在一些数据库中可能需要很长时间(即postgresql,带有innodb的mysql)。
顺便说一下,尝试在django中使用通用视图,ListView就可以了。
答案 2 :(得分:0)
QuerySet
是一个懒惰的对象。分配contact_list = Contacts.objects.all()
时,Django不会命中数据库。在您调用count()
,filter()
,first()
,...或contact_list[1:5]
等方法之前,Django将真正从数据库中检索数据。 Django生成的SQL语句将与每个方法相关联,并且这些SQL语句将被发送到DB。
例如:contact_list[1:5]
生成一个包含LIMIT
和OFFSET
条款的SQL语句。
在Paginator
类中,QuerySet
将传递给其构造函数
paginator = Paginator(contact_list, 25)
当您致电paginator.page(page)
时,会调用该语句:
return self._get_page(self.object_list[bottom:top], number, self)
答案 3 :(得分:0)
在这里我们使用get_page()
来获取逐页数据(1页包含25个数据)。我建议这样做:
def listing(request):
contact_list = Contacts.objects.all()
paginator = Paginator(contact_list, 25) # Show 25 contacts per page
page = request.GET.get('page')
contacts = paginator.get_page(page)
return render_to_response('list.html', {"contacts": contacts})