Opened 9 years ago
Closed 4 years ago
#25513 closed New feature (fixed)
Refactor the admin paginator customizations to make them reuseable
Reported by: | Vlada Macek | Owned by: | Nick Pope |
---|---|---|---|
Component: | Core (Other) | Version: | dev |
Severity: | Normal | Keywords: | paginator, ellipsis |
Cc: | Triage Stage: | Ready for checkin | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
For large page counts I miss a standard way to display only interesting blocks of page links in the paginator. I guess Django should include one.
What do you think about integrating my implementation to django.core.paginator.Page
drafted below?
Template example at the bottom.
from django.core.paginator import Paginator, Page class EllipsisPaginator(Paginator): def __init__(self, *args, **kwargs): # number of page links to always display after the first page self.start_wing = kwargs.pop('start_wing', 1) # number of page links to always display around the current page self.island_wings = kwargs.pop('island_wings', 2) # number of page links to always display before the last page self.end_wing = kwargs.pop('end_wing', 1) super(EllipsisPaginator, self).__init__(*args, **kwargs) def _get_page(self, *args, **kwargs): return EllipsisPage(*args, **kwargs) class EllipsisPage(Page): def pages_with_ellipsis(self): """ Generates the list of page numbers for large page counts. Yields '...' where the range of links should be omitted. >>> pp = EllipsisPaginator(object_list=range(38), per_page=3) >>> list(pp.page(1).pages_with_ellipsis()) [1, 2, 3, '...', 12, 13] >>> list(pp.page(2).pages_with_ellipsis()) [1, 2, 3, 4, '...', 12, 13] >>> list(pp.page(3).pages_with_ellipsis()) [1, 2, 3, 4, 5, '...', 12, 13] >>> list(pp.page(4).pages_with_ellipsis()) [1, 2, 3, 4, 5, 6, '...', 12, 13] >>> list(pp.page(5).pages_with_ellipsis()) [1, 2, 3, 4, 5, 6, 7, '...', 12, 13] >>> list(pp.page(6).pages_with_ellipsis()) [1, 2, 3, 4, 5, 6, 7, 8, '...', 12, 13] >>> list(pp.page(7).pages_with_ellipsis()) [1, 2, '...', 5, 6, 7, 8, 9, '...', 12, 13] >>> list(pp.page(8).pages_with_ellipsis()) [1, 2, '...', 6, 7, 8, 9, 10, 11, 12, 13] >>> list(pp.page(9).pages_with_ellipsis()) [1, 2, '...', 7, 8, 9, 10, 11, 12, 13] >>> list(pp.page(10).pages_with_ellipsis()) [1, 2, '...', 8, 9, 10, 11, 12, 13] >>> list(pp.page(11).pages_with_ellipsis()) [1, 2, '...', 9, 10, 11, 12, 13] >>> list(pp.page(12).pages_with_ellipsis()) [1, 2, '...', 10, 11, 12, 13] >>> list(pp.page(13).pages_with_ellipsis()) [1, 2, '...', 11, 12, 13] """ num = 1 end_of_start_wing = min(self.paginator.num_pages, self.paginator.start_wing+1) for num in xrange(1, end_of_start_wing+1): yield num island_start = self.number - self.paginator.island_wings if num < island_start-2: yield '...' num = island_start else: num += 1 island_end = min(self.paginator.num_pages, self.number + self.paginator.island_wings) for num in xrange(num, island_end+1): yield num start_of_end_wing = self.paginator.num_pages - self.paginator.end_wing if num < start_of_end_wing-2: yield '...' num = start_of_end_wing else: num += 1 for num in xrange(num, self.paginator.num_pages+1): yield num
Usage in the template:
<ul class="pagination"> <li rel="prev"> <a {% if page.has_previous %}href="?page={{ page.previous_page_number }}"{% endif %}> Previous </a> </li> {% for pg in page.pages_with_ellipsis %} {% if pg != '...' %} <li {% if pg == page.number %}class="active"{% endif %}> <a {% if pg != page.number %}href="?page={{ pg }}"{% endif %}> {{ pg }} </a> </li> {% else %} <li><span>…</span></li> {% endif %} {% endfor %} <li rel="next" {% if page.has_next %}class="highlight"{% endif %}> <a {% if page.has_next %}href="?page={{ page.next_page_number }}"{% endif %}> Next </a> </li> </ul>
Attachments (1)
Change History (14)
by , 9 years ago
Attachment: | shot-20151006-1543.png added |
---|
comment:1 by , 9 years ago
Attached is the screenshot of how it can look.
The method is a simple and effetcive Python generator jumping over iteresting blocks of pages.
comment:2 by , 9 years ago
The admin contains a similar paginator in the form of a template tag. Maybe it would be worth trying to refactoring that into django.core.paginator
so it's more easily reuseable. I'm not sure how well the code will generalize.
comment:3 by , 9 years ago
Summary: | Paginator support for large page counts → Refactor the admin paginator customizations to make them reuseable |
---|---|
Triage Stage: | Unreviewed → Accepted |
Version: | 1.9a1 → master |
comment:4 by , 9 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
comment:6 by , 9 years ago
Needs documentation: | set |
---|
Looks like it's on the right track, but the new class should be documented too.
comment:8 by , 6 years ago
Patch needs improvement: | set |
---|
comment:9 by , 4 years ago
Keywords: | ellipsis added |
---|---|
Owner: | changed from | to
Patch needs improvement: | unset |
Updated with a new PR.
comment:10 by , 4 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
A screenshot of the paginator.