snippetpythonMinor
how to generate numbers for pagination?
Viewed 0 times
paginationnumbersgenerateforhow
Problem
I made a function that returns the number displayed for pagination. I want to get something like this (parentheses is the only show where the active site):
if pages 10
where [30] is active page. If active page < 3
etc. My code:
How to do it better?
if pages 10
1 2 3 ... 20 [30] 40 ... 78 79 80where [30] is active page. If active page < 3
1 2 [3] 4 ... 20 30 40 ... 78 79 80etc. My code:
count_all - number of all items
items_on_page - items displayed on one page
page - current page
countpages = int(float(count_all+(items_on_page-1))/float(items_on_page))
linkitems = 10
if countpages > (linkitems-1):
countpagesstr = list()
for i in range(1,int(float(linkitems+(2))/float(3))):
countpagesstr += [str(i)]
countpagesstr += ['...']
sr = int(countpages/2)
for i in range(sr-1, sr+1):
countpagesstr += [str(i)]
countpagesstr += ['...']
for i in range(countpages-3, countpages):
countpagesstr += [str(i)]
else:
cp = list()
for c in range(1,countpages+1):
cp.append(str(c))
countpagesstr = cp
return countpagesstrHow to do it better?
Solution
-
Your code doesn't run as written. It needs a function definition.
-
Your design needs work. Suppose the current page is 30 and the list of pages says "... 20 [30] 40 ..." as in your example. How do I get to page 29 or page 31? It doesn't look as if these page numbers will ever appear in the list.
The more usual design is to always show a small number of pages at the beginning and end, and a small number of pages adjacent to the current page. So that the list of pages would look more like "1 2 3 ... 28 29 [30] 31 32 ... 78 79 80".
-
The expression
is unnecessarily complex. You can use Python's floor division operator (
-
Your variables are poorly and unsystematically named.
-
It is easiest conceptually to separate the two steps of deciding which page numbers to show and showing them in order with ellipses.
In the code below I build the set of the page numbers from the first three pages, the five pages around the current page, and the last three pages. I use Python's sets so that I can take this union without having to worry about duplicate page numbers.
Your code doesn't run as written. It needs a function definition.
-
Your design needs work. Suppose the current page is 30 and the list of pages says "... 20 [30] 40 ..." as in your example. How do I get to page 29 or page 31? It doesn't look as if these page numbers will ever appear in the list.
The more usual design is to always show a small number of pages at the beginning and end, and a small number of pages adjacent to the current page. So that the list of pages would look more like "1 2 3 ... 28 29 [30] 31 32 ... 78 79 80".
-
The expression
int(float(count_all+(items_on_page-1))/float(items_on_page))is unnecessarily complex. You can use Python's floor division operator (
//) to achieve the same thing without converting to floats and back again:(count_all + items_on_page - 1) // items_on_page-
Your variables are poorly and unsystematically named.
count_all, for example. All what? Or countpagesstr, which sounds like it might be a string, but is in fact a list. You use underscores in some cases (count_all) but not in others (countpages).-
It is easiest conceptually to separate the two steps of deciding which page numbers to show and showing them in order with ellipses.
In the code below I build the set of the page numbers from the first three pages, the five pages around the current page, and the last three pages. I use Python's sets so that I can take this union without having to worry about duplicate page numbers.
def abbreviated_pages(n, page):
"""
Return a string containing the list of numbers from 1 to `n`, with
`page` indicated, and abbreviated with ellipses if too long.
>>> abbreviated_pages(5, 3)
'1 2 [3] 4 5'
>>> abbreviated_pages(10, 10)
'1 2 3 4 5 6 7 8 9 [10]'
>>> abbreviated_pages(20, 1)
'[1] 2 3 ... 18 19 20'
>>> abbreviated_pages(80, 30)
'1 2 3 ... 28 29 [30] 31 32 ... 78 79 80'
"""
assert(0 < n)
assert(0 < page <= n)
# Build set of pages to display
if n <= 10:
pages = set(range(1, n + 1))
else:
pages = (set(range(1, 4))
| set(range(max(1, page - 2), min(page + 3, n + 1)))
| set(range(n - 2, n + 1)))
# Display pages in order with ellipses
def display():
last_page = 0
for p in sorted(pages):
if p != last_page + 1: yield '...'
yield ('[{0}]' if p == page else '{0}').format(p)
last_page = p
return ' '.join(display())Code Snippets
int(float(count_all+(items_on_page-1))/float(items_on_page))(count_all + items_on_page - 1) // items_on_pagedef abbreviated_pages(n, page):
"""
Return a string containing the list of numbers from 1 to `n`, with
`page` indicated, and abbreviated with ellipses if too long.
>>> abbreviated_pages(5, 3)
'1 2 [3] 4 5'
>>> abbreviated_pages(10, 10)
'1 2 3 4 5 6 7 8 9 [10]'
>>> abbreviated_pages(20, 1)
'[1] 2 3 ... 18 19 20'
>>> abbreviated_pages(80, 30)
'1 2 3 ... 28 29 [30] 31 32 ... 78 79 80'
"""
assert(0 < n)
assert(0 < page <= n)
# Build set of pages to display
if n <= 10:
pages = set(range(1, n + 1))
else:
pages = (set(range(1, 4))
| set(range(max(1, page - 2), min(page + 3, n + 1)))
| set(range(n - 2, n + 1)))
# Display pages in order with ellipses
def display():
last_page = 0
for p in sorted(pages):
if p != last_page + 1: yield '...'
yield ('[{0}]' if p == page else '{0}').format(p)
last_page = p
return ' '.join(display())Context
StackExchange Code Review Q#15235, answer score: 8
Revisions (0)
No revisions yet.