python_django_Pagination

分頁查詢

當數據量過大時,可能會導致各種各樣的問題發生,例如:服務器資源被耗盡,因數據傳輸量過大而使處理超時,等等。最終都會導致查詢無法完成。
解決這個問題的一個策略就是“分頁查詢”,也就是說不要一次性查詢所有的數據,每次只查詢一“頁“的數據。這樣分批次地進行處理,可以呈現出很好的用戶體驗,對服務器資源的消耗也不大。

打一個比方,有很多很多人要過河,而只有一條船擺渡。若讓所有人都上船,肯定會導致沉船(資源耗盡);若換一條超大的船,除了換船要很高的成本外,上船下船也要耗費很長時間。
所以最好的解決方法是,根據船的容量,每次只上一部分人。等這一船人過河以後,再擺渡下一批人。


 

Django provides a few classes that help you manage paginated data – that is, data that’s split across several pages, with “Previous/Next” links. These classes live in django/core/paginator.py.

Example

Give Paginator a list of objects, plus the number of items you’d like to have on each page, and it gives you methods for accessing the items for each page:

from django.core.paginator import Paginator
>>> objects = ['john', 'paul', 'george', 'ringo']
>>> p = Paginator(objects, 2)

>>> p.count
4
>>> p.num_pages
2
>>> type(p.page_range)  # `<type 'rangeiterator'>` in Python 2.
<class 'range_iterator'>
>>> p.page_range
range(1, 3)

>>> page1 = p.page(1)
>>> page1
<Page 1 of 2>
>>> page1.object_list
['john', 'paul']

>>> page2 = p.page(2)
>>> page2.object_list
['george', 'ringo']
>>> page2.has_next()
False
>>> page2.has_previous()
True
>>> page2.has_other_pages()
True
>>> page2.next_page_number()
Traceback (most recent call last):
...
EmptyPage: That page contains no results
>>> page2.previous_page_number()
1
>>> page2.start_index() # The 1-based index of the first item on this page
3
>>> page2.end_index() # The 1-based index of the last item on this page
4

>>> p.page(0)
Traceback (most recent call last):
...
EmptyPage: That page number is less than 1
>>> p.page(3)
Traceback (most recent call last):
...
EmptyPage: That page contains no results

 

請注意,可以給paginator一個列表/元組、一個django查詢集或任何其他帶有count()或uu len_uuu()方法的對象。當確定傳遞對象中包含的對象數時,paginator將首先嚐試調用count(),如果傳遞的對象沒有count()方法,則返回到使用len()。這允許Django的queryset等對象在可用時使用更有效的count()方法。

 

Using Paginator in a view

下面是一個稍微複雜一些的例子,在視圖中使用paginator來對查詢集分頁。我們提供視圖和附帶的模板來顯示如何顯示結果。此示例假定您有一個已導入的聯繫人模型。

View函數如下所示:

from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.shortcuts import render

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(request, 'list.html', {'contacts': contacts})

 

In the template list.html, you’ll want to include navigation between pages along with any interesting information from the objects themselves:

 

{% for contact in contacts %}
    {# Each "contact" is a Contact model object. #}
    {{ contact.full_name|upper }}<br />
    ...
{% endfor %}

<div class="pagination">
    <span class="step-links">
        {% if contacts.has_previous %}
            <a href="?page={{ contacts.previous_page_number }}">previous</a>
        {% endif %}

        <span class="current">
            Page {{ contacts.number }} of {{ contacts.paginator.num_pages }}.
        </span>

        {% if contacts.has_next %}
            <a href="?page={{ contacts.next_page_number }}">next</a>
        {% endif %}
    </span>
</div>

 

 

Paginator objects

The Paginator class has this constructor:

class Paginator(object_listper_pageorphans=0allow_empty_first_page=True)[source]

Required argument

object_list

A list, tuple, QuerySet, or other sliceable object with a count() or __len__() method. For consistent pagination, QuerySets should be ordered, e.g. with an order_by() clause or with a default ordering on the model.

-------

Performance issues paginating large QuerySets
If you’re using a QuerySet with a very large number of items, requesting high page numbers might be slow on some databases, because the resulting LIMIT/OFFSET query needs to count the number of OFFSET records which takes longer as the page number gets higher.

per_page
The maximum number of items to include on a page, not including orphans (see the orphans optional argument below).


Optional arguments

orphans
The minimum number of items allowed on the last page, defaults to zero. Use this when you don’t want to have a last page with very few items. If the last page would normally have a number of items less than or equal to orphans, then those items will be added to the previous page (which becomes the last page) instead of leaving the items on a page by themselves. For example, with 23 items, per_page=10, and orphans=3, there will be two pages; the first page with 10 items and the second (and last) page with 13 items.

allow_empty_first_page

Whether or not the first page is allowed to be empty. If False and object_list is empty, then an EmptyPage error will be raised.

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章