1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 | from django import template
from django.db.models.query import QuerySet
from django.core.paginator import Paginator, QuerySetPaginator
register = template.Library()
class PaginateNode(template.Node):
def __init__(self, objlist_name, nr_pages, var_name="page", param_name="page"):
self.objlist_name = objlist_name
self.nr_pages = nr_pages
self.var_name = var_name
self.param_name = param_name
def render(self, context):
try:
list_or_queryset = context[self.objlist_name]
except KeyError:
return ''
if isinstance(list_or_queryset, QuerySet):
paginator = QuerySetPaginator(list_or_queryset, self.nr_pages)
else:
paginator = Paginator(list_or_queryset, self.nr_pages)
try:
page = int(context['request'].REQUEST.get(self.param_name, 1))
except:
page = 1
context[self.var_name] = paginator.page(page)
context[self.var_name+"_set"] = paginator
# backward compatibility injections into the context
context[self.var_name+"_count"] = paginator.count
context[self.var_name+"_num_pages"] = paginator.num_pages
context[self.var_name+"_page_range"] = paginator.page_range
return ''
def paginate(parser, token):
try:
tag_name, arg = token.contents.split(None, 1)
except ValueError:
raise template.TemplateSyntaxError, "%r tag requires arguments" % token.contents.split()[0]
args = arg.split(None)
var_name = "page"
param_name = "page"
try:
objlist_name = args[0]
nr_pages = args[1]
except:
raise template.TemplateSyntaxError, "%r tag invalid arguments" % token.contents.split()[0]
if len(args)==2:
pass
elif len(args)==4 and args[2]=="as":
var_name = args[3]
elif len(args)==6 and args[4]=="using":
var_name = args[3]
param_name = args[5]
else:
raise template.TemplateSyntaxError, "%r tag invalid arguments" % token.contents.split()[0]
try:
nr_pages = int(nr_pages)
except:
raise template.TemplateSyntaxError, "%r tag invalid arguments" % token.contents.split()[0]
return PaginateNode(objlist_name, nr_pages, var_name, param_name)
paginate = register.tag(paginate)
|
Comments
It probably merits mentioning that this tag depends on 'django.core.context_processors.request' being added to settings.TEMPLATE_CONTEXT_PROCESSORS, as this is a non-default configuration.
#
Thanks wam, text has been updated.
I've also added a new variable in the context called "page_set" or otherwise var_name+"_set" which contains the paginator object.
However since the paginator object does not implement __len__ and alikes so you cannot use {{ page_set|count }} instead you need the call the method {{ page_set.count }} or for example with the humanize contrib {{ page_set.count|apnumber }} .
The old names are still there for backwards compatibility. (But might be removed in the future as it clutters the context)
#
I can't seem to get past a KeyError at the line:
list_or_queryset = context[self.objlist_name]
Which I would guess means I'm not passing the request object properly, but I do have django.core.context_processors.request added to settings.py. Is there something else that needs to be considered?
For what it's worth, Here's what I'm doing in the template: {% paginate category.product_set.active 10 %}
#
The snippet should be updated to lookup the variable with the template tags resolve_variable api.
Currently it requires you to put the list_or_queryset directly into the template context.
Since the other paginator tag seems to be far far more popular then mine, i will not spend much more time on this. If anyone wants to make a patch (and remind me of it, cause djangosnippets doesn't send mails) I'll happily apply it and update the snippet.
#
there's a bug in the template example code. the 'for' is closed by an 'endif'.
thanks for the snippet, I found it very usefull indeed for my usecase. hope you feel encouraged to keep maintaining the snippet.
#
thnx schraal, updated the example code. i'll hope to update the tag for 1.0 once it is released.
#