Pull to refresh

Делим на страницы

Reading time4 min
Views11K
Практически в любом сайте есть нужда разбить вывод информации на страницы. В джанге уже есть некоторые вещи которые помогут в написании своего пагинатора, но вот что бы взять и в две строчки сделать пагинацию для любой вьюшки — такого пока не встречал.

Я решил написать такой, благо идея как его сделать у меня зародилась уже давно. Итак встречаем, django-simplepagination.



Пагинатор по сути является декоратором, который вы ставите над вашей вьюшкой с одним условием. Условие очень простое, вьюшка должна возвращать словарь, а не HttpResponse. Если вы используйте самописный декоратор render_to или пользуетесь таковым из django-annoying то все условия для разбития на страницы соблюдены. Дальше всё очень просто, инсталируете django-simplepagination, добавляете 'simplepagination' в INSTALLED_APPS и ставите декоратор над вьюшкой. Для примера:

from simplepagination import paginate
from annoying.decorators import render_to
from blog.models import Post

@render_to('blog_posts.html')
@paginate(style='digg', per_page=15)
def list_posts(request):
    posts = Post.objects.all()
    return {'object_list': posts}


Далее в темплейте 'blog_posts.html' вы вставляете {% include paginator.template %}, так же не забудьте в базовом шаблоне подключить paginator.css файл.

На этом создание копии digg пагинации заканчивается.

Естественный вопрос, как происходит что из трёх строчек кода, очень сложный по логике и виду дигг'овский пагинатор работает? Объясню, логика пагинаторов описывается в так называемых backend'ах. Бэкенд digg'а уже встроен в приложение, он так же является примером для тех кто хочет написать свой бэкенд. Кроме логики нужен конечно же и html, он тоже встроен в приложение, как и css со стилями для digg пагинатора.

Конечно вряд ли ваш сайт использует именно digg версию пагинатора, поэтому я покажу вам как написать свой бэкенд, для примера возьмём пагинацию хабрахабра.

Итак первым делом вам нужно создать класс наследующийся от simplepagination.backends.Paginator. Сама логика лежит внутри функции paginate которая обязана быть в вашем классе.

from simplepagination.backends import Paginator

class HabrahabrPaginator(Paginator):
    def paginate(self, frame_size, number_of_pages, current_page):
        output = {}
        if current_page > 1:
            output['prev'= current_page - 1
        if current_page < number_of_pages:
            output['next'= current_page + 1
        if current_page + frame_size - 1 < number_of_pages:
            output['last'= number_of_pages
        if current_page - frame_size + 1 > 1:
            output['first'= 1
        if number_of_pages <= frame_size:
            output['pages'= range(1, number_of_pages + 1)
        else:
            output['pages'= range(max(current_page - frame_size + 11), min(current_page + frame_size, number_of_pages + 1))
        return output


После того как бэкенд срабатывает, в словарь который возвращает вьюшка добавляется этот output под именем 'paginator' и соответственно попадает в ваш темплейт.

Теперь дело за малым, выдрать хтмл и css из хабра (я сделал это за вас, заодно префикснул имена классов что бы они не совпали с теми которые могут уже быть на вашем сайте), сохранить хтмл под именем paginator_habrahabr.html и подключить сохранёный цсс.

Последняя вещь которую нужно сделать, это добавить ваш бэкенд в словарь бэкендов. Откройте settings.py вашего сайта и добавьте следующую строчку (измените путь до вашего класса на нужный).

PAGINATION_BACKENDS = {'habrahabr': 'path.to.HabrahabrPaginator'}

На этом возможности приложения не заканчиваются, можно использовать несколько стилей пагинации на одном сайте, у всех вещей есть дефолтные настройки, которые можно изменить как общими настройками определённого бэкенда так и параметрами передаваемыми в декоратор. Советую глянуть на файл settings.py и почитать описания настроек.
Tags:
Hubs:
Total votes 51: ↑45 and ↓6+39
Comments55

Articles