Paginação¶
O Django fornece algumas classes que ajudam a lidar com paginação de dados –
isto é, dados que são divididos entre várias páginas, com links “Previous/Next”.
Essas classes estão contidas no módulo django/core/paginator.py
.
Exemplo¶
Dada a um Paginator
uma lista de objetos, mais um número de itens que você
gostaria que aparececem em cada página, ele fornecerá os métodos necessários
para acessar os itens de cada página:
>>> from django.core.paginator import Paginator
>>> objects = ['john', 'paul', 'george', 'ringo']
>>> p = Paginator(objects, 2)
>>> p.count
4
>>> p.num_pages
2
>>> p.page_range
[1, 2]
>>> 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()
3
>>> page2.previous_page_number()
1
>>> page2.start_index() # O índice iniciado em 1 do primeiro item nesta página
3
>>> page2.end_index() # O índice iniciado em 1 do último item nesta página
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
Note
Note que você pode dar a um paginador uma lista ou tupla Paginator
, uma
QuerySet
do Django, ou qualquer objeto com um método count()
ou
__len__()
. Ao determinar o número de objetos contidos no objeto passado,
o Paginator
vai primeiro tentar chamar count()
, depois irá tentar
chamar len()
se o objeto não tiver um método count()
. Isso permite a
objetos como o QuerySet
do Django usarem um count()
mais eficiente,
quando disponível.
Usando Paginator
em uma view¶
Aqui há um exemplo ligeiramente mais complexo do uso do Paginator
em
um view para paginar um queryset. Nós dizemos a ambos, view e o template que o
acompanha, como você pode exibir resultados. Este exemplo assume que você tem um
model Contacts
que já foi importado.
A função view parece com isso:
from django.core.paginator import Paginator, InvalidPage, EmptyPage
def listing(request):
contact_list = Contacts.objects.all()
paginator = Paginator(contact_list, 25) # Mostra 25 contatos por página
# Make sure page request is an int. If not, deliver first page.
# Esteja certo de que o `page request` é um inteiro. Se não, mostre a primeira página.
try:
page = int(request.GET.get('page', '1'))
except ValueError:
page = 1
# Se o page request (9999) está fora da lista, mostre a última página.
try:
contacts = paginator.page(page)
except (EmptyPage, InvalidPage):
contacts = paginator.page(paginator.num_pages)
return render_to_response('list.html', {"contacts": contacts})
No template list.html
, você poderá incluir a navegação entre as páginas,
juntamente com qualquer informação interessante a partir dos próprios objetos:
{% for contact in contacts.object_list %}
{# Cada "contato" é um objeto do model Contact. #}
{{ contact.full_name|upper }}<br />
...
{% endfor %}
<div class="pagination">
<span class="step-links">
{% if contacts.has_previous %}
<a href="?page={{ contacts.previous_page_number }}">anterior</a>
{% endif %}
<span class="current">
Página {{ contacts.number }} of {{ contacts.paginator.num_pages }}.
</span>
{% if contacts.has_next %}
<a href="?page={{ contacts.next_page_number }}">próxima</a>
{% endif %}
</span>
</div>
Objetos Paginator
¶
A classe Paginator
tem este construtor:
-
class
Paginator
(object_list, per_page, orphans=0, allow_empty_first_page=True)¶
Argumentos obrigatórios¶
object_list
- Uma lista, tupla,
QuerySet
do Django, ou outro objeto contável por um métodocount()
ou__len__()
. per_page
- O número máximo de ítens que serão incluídos na página, não incluíndo
orfãos (veja o argumento opcional
orphans
abaixo).
Argumentos opcionais¶
orphans
- O número mínimo de ítens permitidos em uma última página, o padrão é zero.
Use isto quando você não quiser ter uma última página com pouquíssimos
ítens. Se a última página poderá ter um número de ítens menor que ou igual
ao
orphans
, então estes ítens serão adicionados na página anterior (que se torna a última página) ao invés de deixados em uma página só para eles. Por exemplo, com 23 ítens,per_pager=10
, eorphans=3
, haverá duas páginas; a primeira com 10 ítens e a segunda (e última) com 13 ítems. allow_empty_first_page
- Permite ou não a primeira página ser vazia. Se for
False
eobject_list
estiver vazio, então um erroEmtpyPage
será levantado.
Métodos¶
-
Paginator.
page
(number)¶ Retorna um objeto
Page
com um determinado índice. Se a determinada página não existe, é lançado uma exceçãoInvalidPage
.
Atributos¶
-
Paginator.
count
¶ O número total de objetos, através de todas as páginas.
Note
Quando se determina o número de objetos contidos no
object_list
, oPaginator
irá primeiro tentar chamarobject_list.count()
. Seobject_list
não tem o métodocount()
, então oPaginator
tentará usar oobject_list.__len__()
. Isto permite objetos, como umQuerySet
do Django, usar um método decount()
mais eficiente quando disponível.
-
Paginator.
num_pages
¶ O número total de páginas.
-
Paginator.
page_range
¶ Um número começando com 1 de páginas, por exemplo,
[1, 2, 3, 4]
.
Exceções InvalidPage
¶
O método page()
lança a exceção InvalidPage
se a página requisitada for
inválida (ex., não for um inteiro) ou não conter objetos. Geralmente,
isto é suficiente para se ter uma exceção InvalidPage
, mas se você quizer
mais granularidade, você pode utilizar qualquer uma dessas exceções:
PageNotAnInteger
- Lançada quando à
page()
é dado um valor que não é um inteiro. EmptyPage
- Lançada quando à
page()
é dado um valor válido, mas não á objetos existentes naquela página.
Ambas as exceções são subclasses de InvalidPage
, então você poder
manipulá-las com um simples except InvalidPage
.
Objetos Page
¶
-
Page(object_list, number, paginator):
Você normalmente não iŕa construir Pages
na mão – você vai
obtê-los usando Paginator.page()
.
Métodos¶
-
Page.
has_next
()¶ Retorna
True
se existe uma página subseqüente.
-
Page.
has_previous
()¶ Retorna
True
se existe uma página anterior.
-
Page.
has_other_pages
()¶ Retorna
True
se existe uma página subsequente ou anterior.
-
Page.
next_page_number
()¶ Retorna o número da página subseqüente. Note que este é um método “burro” e vai apenas retornar o número da página subseqüente, a página existindo ou não.
-
Page.
previous_page_number
()¶ Retorna o número da página anterior. Note que este é um método “burro” e vai apenas retornar o número da página anterior, a página existindo ou não.
-
Page.
start_index
()¶ Retorna o índice iniciado em 1 do primeiro objeto na página, relativo a todos os objetos na lista do paginador. Por exemplo, quando se pagina uma lista com 5 objetos a 2 objetos por página, o
start_index()
da segunda página devolveria3
.
-
Page.
end_index
()¶ Retorna o índice iniciado em 1 do último objeto na página, relativo a todos os objetos na lista do paginador. Por exemplo, quando se pagina uma lista com 5 objetos a 2 objetos por página, o
end_index()
da segunda página devolveria4
.