Last active
December 13, 2015 23:59
-
-
Save rhblind/4995490 to your computer and use it in GitHub Desktop.
Django pagination template tag.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
from django import template | |
from django.utils.encoding import smart_unicode | |
register = template.Library() | |
class PaginateNode(template.Node): | |
""" | |
Pagination template node. | |
""" | |
@classmethod | |
def handle_token(cls, parser, token): | |
""" | |
Class method for parsing token and returning a Node | |
""" | |
tokens = token.contents.split() | |
if len(tokens) == 3: | |
if not (tokens[1].isalpha() and tokens[1] in "previous next"): | |
raise template.TemplateSyntaxError("Valid arguments to %r is 'previous' or 'next'" % tokens[0]) | |
return cls(direction=tokens[1], page_expr=parser.compile_filter(tokens[2])) | |
else: | |
raise template.TemplateSyntaxError("%r tag requires exactly two argument" % tokens[0]) | |
def __init__(self, direction=None, page_expr=None): | |
if direction is None: | |
raise template.TemplateSyntaxError("PaginateNode requires a paginate direction") | |
if page_expr is None: | |
raise template.TemplateSyntaxError("PaginateNode requires a Page() instance context variable") | |
self.direction = direction | |
self.page_expr = page_expr | |
def render(self, context): | |
""" | |
Build and returns the querystring. | |
""" | |
return smart_unicode("&".join((self.get_page_string(context), | |
self.get_get_string(context)))) | |
def get_page_string(self, context): | |
""" | |
Returns the page string part | |
of the querystring. | |
""" | |
page = self.page_expr.resolve(context) | |
if self.direction == u"next" and page.has_next(): | |
next_page = page.next_page_number() | |
elif self.direction == u"previous" and page.has_previous(): | |
next_page = page.previous_page_number() | |
else: | |
next_page = page.number | |
return smart_unicode("?page=%(page)s" % {"page": next_page}) | |
def get_get_string(self, context): | |
""" | |
Returns the GET string part of | |
the querystring. | |
""" | |
get_data = context["request"].GET | |
def build_str(query_dict): | |
""" | |
Yields querystring items for | |
GET data | |
""" | |
page = self.page_expr.var | |
q_dict = query_dict.copy() | |
for key, value in q_dict.iterlists(): | |
# Make sure we don't get the page context | |
# variable here | |
if key == page.var: | |
continue | |
if len(value) > 1: | |
for item in value: | |
yield "%(key)s=%(value)s" % {"key": key, "value": item} | |
elif len(value): | |
item = value.pop() | |
yield "%(key)s=%(value)s" % {"key": key, "value": item} | |
else: | |
continue | |
return smart_unicode("&".join(build_str(get_data))) | |
@register.tag | |
def paginate(parser, token): | |
""" | |
Returns a querystring suitable to pass in a GET request for | |
obtaining the next page in a paginator. Must be passed | |
a Page() context variable. | |
Example:: | |
<a href="{% paginate previous page %}">Previous page</a> | |
or | |
<a href="{% paginate next page %}">Next page</a> | |
""" | |
return PaginateNode.handle_token(parser, token) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment