Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pagination of Date-Based Generic Views in Django

I have a pretty simple question. I want to make some date-based generic views on a Django site, but I also want to paginate them. According to the documentation the object_list view has page and paginate_by arguments, but the archive_month view does not. What's the "right" way to do it?

like image 452
Apreche Avatar asked Mar 21 '09 20:03

Apreche


People also ask

Does pagination improve performance Django?

Additionally, switching to keyset pagination will improve the performance of page lookups and make them work in constant time. Django makes it easy to alter its default configuration, giving you the power to build a performant solution for pagination in Django.

What is pagination in Django rest?

Django provides a few classes that help you manage paginated data – that is, data that's split across several pages, with “Previous/Next” links. — Django documentation. REST framework includes support for customizable pagination styles.


2 Answers

I created a template tag to do template-based pagination on collections passed to the templates that aren't already paginated. Copy the following code to an app/templatetags/pagify.py file.

from django.template import Library, Node, Variable
from django.core.paginator import Paginator
import settings

register = Library()

class PagifyNode(Node):
    def __init__(self, items, page_size, varname):
        self.items = Variable(items)
        self.page_size = int(page_size)
        self.varname = varname

    def render(self, context):
        pages = Paginator(self.items.resolve(context), self.page_size)
        request = context['request']
        page_num = int(request.GET.get('page', 1))

        context[self.varname] = pages.page(page_num)
        return ''

@register.tag
def pagify(parser, token):
    """
    Usage:

    {% pagify items by page_size as varname %}
    """

    bits = token.contents.split()
    if len(bits) != 6:
        raise TemplateSyntaxError, 'pagify tag takes exactly 5 arguments'
    if bits[2] != 'by':
        raise TemplateSyntaxError, 'second argument to pagify tag must be "by"'
    if bits[4] != 'as':
        raise TemplateSyntaxError, 'fourth argument to pagify tag must be "as"'
    return PagifyNode(bits[1], bits[3], bits[5])

To use it in the templates (assume we've passed in an un-paginated list called items):

{% load pagify %}

{% pagify items by 20 as page %}
{% for item in page %}
    {{ item }}
{% endfor %}

The page_size argument (the 20) can be a variable as well. The tag automatically detects page=5 variables in the querystring. And if you ever need to get at the paginator that belong to the page (for a page count, for example), you can simply call:

{{ page.paginator.num_pages }}
like image 135
Soviut Avatar answered Sep 19 '22 02:09

Soviut


Date based generic views don't have pagination. It seems you can't add pagination via wrapping them as well since they return rendered result.

I would simply write my own view in this case. You can check out generic views' code as well, but most of it will probably be unneeded in your case.

Since your question is a valid one, and looking at the code; I wonder why they didn't decouple queryset generation as separate functions. You could just use them and render as you wish then.

like image 26
muhuk Avatar answered Sep 21 '22 02:09

muhuk