1. Mikhail Korobov
  2. django-simplepagination


django-simplepagination / simplepagination / __init__.py

# coding: utf-8

from functools import partial, update_wrapper

from django.utils.datastructures import MultiValueDictKeyError
from django.core.paginator import Paginator, EmptyPage
from django.http import Http404

from . import settings
from .utils import unicode_urlencode, get_instance_from_path

class SimplePaginator(object):
    Class based decorator.

    SimplePagination decorator must be used along with 'render_to' 
    decorator from django-annoying application

    def __init__(self, object_list_item_name='object_list', style=None, per_page=10, 
                frame_size=8, allow_user_per_page=False, fixed_user_per_page=None, 
                template=None, anchor=None):
        Decorator parameters 

        object_list_item_name - Name of the variable with objects that we paginate.
        style - name of pagination backend.
        per_page - number of objects to show on page.
        frame_size - max pages numbers to show.

        self.object_list_item_name = object_list_item_name
        style = style or getattr(settings, "PAGINATION_STYLE", "digg")
        self.backend = get_instance_from_path(settings.PAGINATION_BACKENDS[style])
        self.per_page = per_page
        self.frame_size = frame_size
        self.allow_user_per_page = allow_user_per_page
        self.template = template or 'paginator_%s.html' % style
        self.fixed_user_per_page = fixed_user_per_page
        self.anchor = anchor
    def __call__(self, function):
        Receive decorated function and return
        function decorated with decorate method
        decorated = partial(self.decorate, function)
        return update_wrapper(decorated, self.decorate)
    def decorate(self, function, request, *args, **kwargs):

        # execute view 
        output = function(request, *args, **kwargs)
        # only try to paginate if view returned dictionary,
        # in all other cases just return view output.
        if not isinstance(output, dict):
            return output
        params = request.GET.copy()
            page_num = int(params.pop('page')[0])
        except (ValueError, KeyError):
            page_num = 1
        per_page = self.per_page
        if self.allow_user_per_page and 'per_page' in params:
                user_per_page = int(params['per_page'])
                if not self.fixed_user_per_page or user_per_page not in self.fixed_user_per_page:
                    per_page = user_per_page
            except (ValueError, KeyError):
                params['per_page'] = self.per_page
        elif 'per_page' in params:
            paginate_qs = output.pop(self.object_list_item_name)
        except KeyError:
            raise KeyError("Variable with name '%s', not found in view returned dictionary" % self.object_list_item_name)
        paginator = Paginator(paginate_qs, per_page)
            page = paginator.page(page_num)
        except EmptyPage:
            raise Http404()
        data = {}
        data['page_num'] = page_num # active page number
        data['per_page'] = per_page # items per page
        data['params'] = unicode_urlencode(params) # get parameters
        data['anchor'] = self.anchor # ancor
        data['pages'] = pages = paginator.num_pages # number of pages
        data['paginator_template'] = self.template
        data['allow_user_per_page'] = self.allow_user_per_page

        output[self.object_list_item_name] = page.object_list
        data.update(self.backend.paginate(self.frame_size, pages, page_num))
        output['paginator'] = data
        return output

paginate = SimplePaginator