2012-09-05 42 views
6

我需要製作真正的分頁,而不是分頁所有的retreived數據。 Django文檔站點中的示例如下所示;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中做到這一點?

+1

這個問題已經回答過了,在這裏看到: http://stackoverflow.com/questions/10548744/django-lazy-queryset-and-pagination –

回答

18

你做出一個錯誤的假設。分頁時,Django不會檢索所有對象:適當地對查詢集進行切片,這會在SQL上使用LIMIT和COUNT。

+0

你的意思是;代碼中的Contacts.objects.all()行有問題,不檢索所有記錄? –

+4

正確。查詢集是懶惰的,正如文檔解釋的一樣,並且不會調用db調用,直到它們被迭代或切片。 –

+0

實際上,我應該提到我正在使用MongoDB和Mongo fork進行DJango建模。可能這是針對SQL數據庫的,而不是Mongo fork。因爲我試過了,它仍然從數據庫中獲取所有數據。 DJango可能缺乏Mongo fork。但是,謝謝你,我不知道。 –

0

查看Paginator類(django/core/paginator.py),它只提取所需的頁面。在大表中只有一個問題:如果你想顯示總頁數,你必須在整個表上計算(*),這在一些數據庫中可能需要很長時間(即postgresql,mysql和innodb)。

順便說一句,嘗試在django中使用通用視圖,ListView將在這裏罰款。

0

A QuerySet是一個懶惰的對象。當你指定contact_list = Contacts.objects.all()時,Django不會命中數據庫。在您調用諸如count()filter(),first(),或contact_list[1:5]之類的方法之前,Django會真正從數據庫中檢索數據。 Django生成的SQL語句將與每種方法相關聯,並將這些SQL語句發送到數據庫。

例如:contact_list[1:5]生成的SQL語句有LIMITOFFSET從句。

Paginator類中,QuerySet將傳遞給它的構造

paginator = Paginator(contact_list, 25) 

當你調用paginator.page(page),語句被稱爲:

return self._get_page(self.object_list[bottom:top], number, self)