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?
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.
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.
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 }}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With