Paginacion en django estilo digg

CN Camilo Nova Camilo Nova

Camilo Nova

CEO
2 min read.

La Paginación en django es excelente, permite una flexibilidad importante para solucionar muchos problemas que se presentan al paginar resultados, por ejemplo el problema del cacheo, que se presenta al realizar una consulta que pide todos los datos sabiendo que solo vamos a mostrar unos pocos.

Gracias a la excelente documentación podemos encontrar toda la información aquí:

http://docs.djangoproject.com/en/1.1/topics/pagination/#topics-pagination

Sin embargo, cuando se trabajan volúmenes grandes de información, digamos mas de 50 paginas, se hace dispendioso pasar entre paginas hasta llegar a la que buscamos, por eso es muy útil tener una paginación al estilo Digg que muestra algunas paginas adicionales y no solo el enlace a la anterior y la siguiente.

Tomando como base este excelente trabajo:

http://krisje8.com/blog/2009/jul/02/django-pagination-template-tag-digg-style/

realice algunas modificaciones para que muestre '...' entre las paginas iniciales y la pagina actual, para darle una mejor ubicación al usuario sobre donde se encuentra.

Tenemos el siguiente template_tag:

#! /usr/bin/env python
# -*- coding: utf8 -*-
# render_paginator.py
from django.template import Library

register = Library()

def render_paginator(context, first_last_amount=2, before_after_amount=4):
    page_obj = context['page_obj']
    paginator = context['paginator']
    page_numbers = []

    # Pages before current page
    if page_obj.number > first_last_amount + before_after_amount:
        for i in range(1, first_last_amount + 1):
            page_numbers.append(i)

        page_numbers.append(None)

        for i in range(page_obj.number - before_after_amount, page_obj.number):
            page_numbers.append(i)

    else:
        for i in range(1, page_obj.number):
            page_numbers.append(i)

    # Current page and pages after current page
    if page_obj.number + first_last_amount + before_after_amount < paginator.num_pages:
        for i in range(page_obj.number, page_obj.number + before_after_amount + 1):
            page_numbers.append(i)

        page_numbers.append(None)

        for i in range(paginator.num_pages - first_last_amount + 1, paginator.num_pages + 1):
            page_numbers.append(i)

    else:
        for i in range(page_obj.number, paginator.num_pages + 1):
            page_numbers.append(i)

    return {
        'paginator': paginator,
        'page_obj': page_obj,
        'page_numbers': page_numbers
    }

register.inclusion_tag('layout/pagination.html', takes_context=True)(render_paginator)

Con la siguiente plantilla:

{% if page_obj.has_previous %}
  <a href="?page={{ page_obj.previous_page_number }}">Previous</a>
{% endif %}
{% for page in page_numbers %}
  {% if page %}
    {% ifequal page page_obj.number %}
      <strong>{{ page }}</strong>
    {% else %}
      <a href="?page={{ page }}">{{ page }}</a>
    {% endifequal %}
  {% else %}
    ...
  {% endif %}
{% endfor %}
{% if page_obj.has_next %}
  <a href="?page={{ page_obj.next_page_number }}">Next</a>
{% endif %}

Para usarlo se coloca el siguiente codigo en cualquiera de las plantillas que queramos paginar:

    {% if is_paginated %}
      {% load render_paginator %}
      {% render_paginator 2 3 %}
    {% endif %}

Lo que genera un código como:

Previous  1  2  ... 5  6  7  8  9  10  11  ... 25  26  Next

Lo mejor de todo es que no necesita ningún componente adicional ni interfiere con la paginación por defecto que traen las vistas genéricas en django.


Written by Camilo Nova

CN Camilo Nova Camilo Nova

As the Axiacore CEO, Camilo writes about the intersection of technology, design, and business. With a strategic mindset and a deep understanding of the industry, he is dedicated to helping companies grow.

Newsletter

Subscribe to our newsletter:

Read more

Trabajar para vivir

y no vivir para trabajar...Gracias por los excelentes momentos que pasamos a todos aquellos involucrados con AxiaCore, además...

1 min read.

Symfony interactive shell

The command line interface (known as cli) is a good tool for most developers, due ten fingers make more things than two. In f...

2 min read.

Build Once. Own Forever.