Skip to content

Commit 1ae3701

Browse files
committed
Add 3.2 fix for pagination
1 parent 51f9fb3 commit 1ae3701

File tree

6 files changed

+174
-50
lines changed

6 files changed

+174
-50
lines changed

CHANGELOG.rst

+5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ Changelog
44
Only important changes are mentioned below. See `commit log <https://github.com/darklow/django-suit/commits/develop>`_, `closed issues <https://github.com/darklow/django-suit/issues?direction=desc&sort=updated&state=closed>`_ and `closed pull
55
requests <https://github.com/darklow/django-suit/pulls?q=sort%3Aupdated-desc+is%3Apr+is%3Aclosed>`_ for full changes.
66

7+
v.0.2.29 (2021-04-28)
8+
--------------------
9+
* This is a 'maintenance fork' which contains some fixes for compatibility with the latest Django releases.
10+
11+
712
v0.2.28 (2019-10-02)
813
--------------------
914

docs/conf.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
# built documents.
5757
#
5858
# The short X.Y version.
59-
version = '0.2.28'
59+
version = '0.2.29'
6060
# The full version, including alpha/beta/rc tags.
6161
release = version
6262

suit/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
VERSION = '0.2.28'
1+
VERSION = '0.2.29'

suit/static/suit/css/suit.css

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

suit/static/suit/less/ui/pagination.less

+67
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
ul {
1010
margin: 0;
1111
}
12+
13+
// Up until Django 3.2
14+
1215
ul li.active a, ul li.active span {
1316
color: #fff;
1417
font-weight: bold;
@@ -29,6 +32,70 @@
2932
line-height: 26px;
3033
padding: 0 10px;
3134
}
35+
36+
37+
// Starting with Django 3.2
38+
39+
// Pages
40+
ul a {
41+
display: inline;
42+
line-height: 26px;
43+
padding: 0 10px;
44+
45+
float: left;
46+
47+
// padding: 4px 12px;
48+
// line-height: 18px;
49+
text-decoration: none;
50+
background-color: #ffffff;
51+
border: 1px solid #dddddd;
52+
border-left-width: 0;
53+
54+
color: #0088cc;
55+
}
56+
57+
// Ellipsis
58+
ul span.disabled {
59+
display: inline;
60+
line-height: 26px;
61+
padding: 0 10px;
62+
63+
float: left;
64+
65+
// padding: 4px 12px;
66+
// line-height: 18px;
67+
text-decoration: none;
68+
background-color: transparent;
69+
border: 1px solid #dddddd;
70+
border-left-width: 0;
71+
72+
color: #999999;
73+
}
74+
75+
// Active page
76+
ul span.this-page {
77+
display: inline;
78+
line-height: 26px;
79+
padding: 0 10px;
80+
81+
float: left;
82+
83+
text-decoration: none;
84+
background-color: #2f96b4;
85+
border: 1px solid #cccccc;
86+
border-left-width: 0;
87+
88+
color: #ffffff;
89+
90+
// Border
91+
border-left-width: 1px;
92+
-webkit-border-top-left-radius: 4px;
93+
-moz-border-radius-topleft: 4px;
94+
border-top-left-radius: 4px;
95+
-webkit-border-bottom-left-radius: 4px;
96+
-moz-border-radius-bottomleft: 4px;
97+
border-bottom-left-radius: 4px;
98+
}
3299
}
33100

34101
.pagination-info {

suit/templatetags/suit_list.py

+99-47
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,23 @@
11
from copy import copy
22
from inspect import getargspec
3+
4+
import django
5+
36
from django import template
47
from django.template.loader import get_template
58
from django.utils.safestring import mark_safe
69
from django.contrib.admin.templatetags.admin_list import result_list
710
from django.contrib.admin.views.main import ALL_VAR, PAGE_VAR
811
from django.utils.html import escape
12+
from django.utils.html import format_html
913
from suit.compat import tpl_context_class
1014

15+
# Starting with Django 3.2, the pagination is 1-based instead of 0-based.
16+
# I've taken the implementations (latest at the time of release 3.2) from https://github.com/django/django/blob/main/django/contrib/admin/templatetags/admin_list.py
17+
# to use in the implementations below. Older versions of django will use the old implementation and will keep working.
18+
# There are corresponding CSS changes in suit/static/suit/less/ui/pagination.less to fix the pagination, as the code below generates different html objects.
19+
USE_NEW_DJANGO_ADMIN_PAGINATION = django.get_version() >= '3.2'
20+
1121
try:
1222
# Python 3.
1323
from urllib.parse import parse_qs
@@ -24,39 +34,68 @@
2434

2535
register = template.Library()
2636

37+
2738
DOT = '.'
2839

2940

3041
@register.simple_tag
3142
def paginator_number(cl, i):
3243
"""
33-
Generates an individual page index link in a paginated list.
44+
Generate an individual page index link in a paginated list.
3445
"""
35-
if i == DOT:
36-
return mark_safe(
37-
'<li class="disabled"><a href="#" onclick="return false;">..'
38-
'.</a></li>')
46+
if not USE_NEW_DJANGO_ADMIN_PAGINATION:
47+
if i == DOT:
48+
return mark_safe(
49+
'<li class="disabled"><a href="#" onclick="return false;">..'
50+
'.</a></li>')
51+
elif i == cl.page_num:
52+
return mark_safe(
53+
'<li class="active"><a href="">%d</a></li> ' % (i + 1))
54+
else:
55+
return mark_safe('<li><a href="%s"%s>%d</a></li> ' % (
56+
escape(cl.get_query_string({PAGE_VAR: i})),
57+
(i == cl.paginator.num_pages - 1 and ' class="end"' or ''),
58+
i + 1))
59+
60+
if i == cl.paginator.ELLIPSIS:
61+
return format_html('<span class="disabled">{}</span> ', cl.paginator.ELLIPSIS)
3962
elif i == cl.page_num:
40-
return mark_safe(
41-
'<li class="active"><a href="">%d</a></li> ' % (i + 1))
63+
return format_html('<span class="this-page">{}</span> ', i)
4264
else:
43-
return mark_safe('<li><a href="%s"%s>%d</a></li> ' % (
44-
escape(cl.get_query_string({PAGE_VAR: i})),
45-
(i == cl.paginator.num_pages - 1 and ' class="end"' or ''),
46-
i + 1))
65+
return format_html(
66+
'<a href="{}"{}>{}</a> ',
67+
cl.get_query_string({PAGE_VAR: i}),
68+
mark_safe(' class="end"' if i == cl.paginator.num_pages else ''),
69+
i,
70+
)
4771

4872

4973
@register.simple_tag
5074
def paginator_info(cl):
75+
if not USE_NEW_DJANGO_ADMIN_PAGINATION:
76+
paginator = cl.paginator
77+
78+
# If we show all rows of list (without pagination)
79+
if cl.show_all and cl.can_show_all:
80+
entries_from = 1 if paginator.count > 0 else 0
81+
entries_to = paginator.count
82+
else:
83+
entries_from = (
84+
(paginator.per_page * cl.page_num) + 1) if paginator.count > 0 else 0
85+
entries_to = entries_from - 1 + paginator.per_page
86+
if paginator.count < entries_to:
87+
entries_to = paginator.count
88+
89+
return '%s - %s' % (entries_from, entries_to)
90+
5191
paginator = cl.paginator
5292

5393
# If we show all rows of list (without pagination)
5494
if cl.show_all and cl.can_show_all:
5595
entries_from = 1 if paginator.count > 0 else 0
5696
entries_to = paginator.count
5797
else:
58-
entries_from = (
59-
(paginator.per_page * cl.page_num) + 1) if paginator.count > 0 else 0
98+
entries_from = ((paginator.per_page * (cl.page_num - 1)) + 1) if paginator.count > 0 else 0
6099
entries_to = entries_from - 1 + paginator.per_page
61100
if paginator.count < entries_to:
62101
entries_to = paginator.count
@@ -67,48 +106,61 @@ def paginator_info(cl):
67106
@register.inclusion_tag('admin/pagination.html')
68107
def pagination(cl):
69108
"""
70-
Generates the series of links to the pages in a paginated list.
109+
Generate the series of links to the pages in a paginated list.
71110
"""
72-
paginator, page_num = cl.paginator, cl.page_num
111+
if not USE_NEW_DJANGO_ADMIN_PAGINATION:
112+
paginator, page_num = cl.paginator, cl.page_num
73113

74-
pagination_required = (not cl.show_all or not cl.can_show_all) \
75-
and cl.multi_page
76-
if not pagination_required:
77-
page_range = []
78-
else:
79-
ON_EACH_SIDE = 3
80-
ON_ENDS = 2
81-
82-
# If there are 10 or fewer pages, display links to every page.
83-
# Otherwise, do some fancy
84-
if paginator.num_pages <= 8:
85-
page_range = range(paginator.num_pages)
86-
else:
87-
# Insert "smart" pagination links, so that there are always ON_ENDS
88-
# links at either end of the list of pages, and there are always
89-
# ON_EACH_SIDE links at either end of the "current page" link.
114+
pagination_required = (not cl.show_all or not cl.can_show_all) \
115+
and cl.multi_page
116+
if not pagination_required:
90117
page_range = []
91-
if page_num > (ON_EACH_SIDE + ON_ENDS):
92-
page_range.extend(range(0, ON_EACH_SIDE - 1))
93-
page_range.append(DOT)
94-
page_range.extend(range(page_num - ON_EACH_SIDE, page_num + 1))
95-
else:
96-
page_range.extend(range(0, page_num + 1))
97-
if page_num < (paginator.num_pages - ON_EACH_SIDE - ON_ENDS - 1):
98-
page_range.extend(
99-
range(page_num + 1, page_num + ON_EACH_SIDE + 1))
100-
page_range.append(DOT)
101-
page_range.extend(
102-
range(paginator.num_pages - ON_ENDS, paginator.num_pages))
103-
else:
104-
page_range.extend(range(page_num + 1, paginator.num_pages))
118+
else:
119+
ON_EACH_SIDE = 3
120+
ON_ENDS = 2
105121

122+
# If there are 10 or fewer pages, display links to every page.
123+
# Otherwise, do some fancy
124+
if paginator.num_pages <= 8:
125+
page_range = range(paginator.num_pages)
126+
else:
127+
# Insert "smart" pagination links, so that there are always ON_ENDS
128+
# links at either end of the list of pages, and there are always
129+
# ON_EACH_SIDE links at either end of the "current page" link.
130+
page_range = []
131+
if page_num > (ON_EACH_SIDE + ON_ENDS):
132+
page_range.extend(range(0, ON_EACH_SIDE - 1))
133+
page_range.append(DOT)
134+
page_range.extend(range(page_num - ON_EACH_SIDE, page_num + 1))
135+
else:
136+
page_range.extend(range(0, page_num + 1))
137+
if page_num < (paginator.num_pages - ON_EACH_SIDE - ON_ENDS - 1):
138+
page_range.extend(
139+
range(page_num + 1, page_num + ON_EACH_SIDE + 1))
140+
page_range.append(DOT)
141+
page_range.extend(
142+
range(paginator.num_pages - ON_ENDS, paginator.num_pages))
143+
else:
144+
page_range.extend(range(page_num + 1, paginator.num_pages))
145+
146+
need_show_all_link = cl.can_show_all and not cl.show_all and cl.multi_page
147+
return {
148+
'cl': cl,
149+
'pagination_required': pagination_required,
150+
'show_all_url': need_show_all_link and cl.get_query_string(
151+
{ALL_VAR: ''}),
152+
'page_range': page_range,
153+
'ALL_VAR': ALL_VAR,
154+
'1': 1,
155+
}
156+
157+
pagination_required = (not cl.show_all or not cl.can_show_all) and cl.multi_page
158+
page_range = cl.paginator.get_elided_page_range(cl.page_num) if pagination_required else []
106159
need_show_all_link = cl.can_show_all and not cl.show_all and cl.multi_page
107160
return {
108161
'cl': cl,
109162
'pagination_required': pagination_required,
110-
'show_all_url': need_show_all_link and cl.get_query_string(
111-
{ALL_VAR: ''}),
163+
'show_all_url': need_show_all_link and cl.get_query_string({ALL_VAR: ''}),
112164
'page_range': page_range,
113165
'ALL_VAR': ALL_VAR,
114166
'1': 1,

0 commit comments

Comments
 (0)