mirror of
https://github.com/nikdoof/test-auth.git
synced 2025-12-14 14:52:15 +00:00
Use Digg style pagination for Corp and Alliance detail views
This commit is contained in:
@@ -35,6 +35,22 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
{% if is_paginated %}
|
||||||
|
<div class="pagination">
|
||||||
|
<ul>
|
||||||
|
<li class="prev{% if not page_obj.has_previous %} disabled{% endif %}"><a href="{% if page_obj.has_previous %}?page={{ page_obj.previous_page_number }}{% endif %}">Previous</a></li>
|
||||||
|
{% for i in page_obj.page_range %}
|
||||||
|
{% if not i %}
|
||||||
|
<li><a href="#">...</a></li>
|
||||||
|
{% else %}
|
||||||
|
<li{% if i == page_obj.number %} class="active"{% endif %}><a href="?page={{ i }}">{{ i }}</a></li>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
<li class="next{% if not page_obj.has_next %} disabled{% endif %}"><a href="{% if page_obj.has_next %}?page={{page_obj.next_page_number }}{% endif %}">Next</a>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
<script src="{{ STATIC_URL }}js/jquery.tablesorter.min.js"></script>
|
<script src="{{ STATIC_URL }}js/jquery.tablesorter.min.js"></script>
|
||||||
<script >
|
<script >
|
||||||
|
|||||||
@@ -40,6 +40,23 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
{% if is_paginated %}
|
||||||
|
<div class="pagination">
|
||||||
|
<ul>
|
||||||
|
<li class="prev{% if not page_obj.has_previous %} disabled{% endif %}"><a href="{% if page_obj.has_previous %}?page={{ page_obj.previous_page_number }}{% endif %}">Previous</a></li>
|
||||||
|
{% for i in page_obj.page_range %}
|
||||||
|
{% if not i %}
|
||||||
|
<li><a href="#">...</a></li>
|
||||||
|
{% else %}
|
||||||
|
<li{% if i == page_obj.number %} class="active"{% endif %}><a href="?page={{ i }}">{{ i }}</a></li>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
<li class="next{% if not page_obj.has_next %} disabled{% endif %}"><a href="{% if page_obj.has_next %}?page={{page_obj.next_page_number }}{% endif %}">Next</a>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
<p><a href="{% url eveapi-corporation-members-csv corporation.id %}" class="btn" title="Exports the membership list of this corporation to a CSV file.">Export as CSV</a></p>
|
<p><a href="{% url eveapi-corporation-members-csv corporation.id %}" class="btn" title="Exports the membership list of this corporation to a CSV file.">Export as CSV</a></p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ from eve_api.forms import EveAPIForm
|
|||||||
from eve_api.models import EVEAccount, EVEPlayerCharacter, EVEPlayerCorporation, EVEPlayerAlliance
|
from eve_api.models import EVEAccount, EVEPlayerCharacter, EVEPlayerCorporation, EVEPlayerAlliance
|
||||||
from eve_api.tasks import import_apikey_result
|
from eve_api.tasks import import_apikey_result
|
||||||
from eve_api.utils import basic_xml_parse_doc
|
from eve_api.utils import basic_xml_parse_doc
|
||||||
|
from eve_api.views.mixins import DetailPaginationMixin
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def eveapi_add(request, post_save_redirect='/', template='eve_api/add.html'):
|
def eveapi_add(request, post_save_redirect='/', template='eve_api/add.html'):
|
||||||
@@ -198,16 +198,19 @@ def eveapi_character(request, charid=None, template='eve_api/character.html', li
|
|||||||
return render_to_response(list_template, context, context_instance=RequestContext(request))
|
return render_to_response(list_template, context, context_instance=RequestContext(request))
|
||||||
|
|
||||||
|
|
||||||
class EVEAPICorporationView(DetailView):
|
class EVEAPICorporationView(DetailPaginationMixin, DetailView):
|
||||||
|
|
||||||
model = EVEPlayerCorporation
|
model = EVEPlayerCorporation
|
||||||
template_name = 'eve_api/corporation.html'
|
template_name = 'eve_api/corporation.html'
|
||||||
|
detail_queryset_name = 'members'
|
||||||
|
|
||||||
|
def get_pagination_queryset(self):
|
||||||
|
return self.object.eveplayercharacter_set.select_related('eveaccount', 'roles').order_by('corporation_date').only('id', 'name', 'corporation_date')
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
ctx = super(EVEAPICorporationView, self).get_context_data(**kwargs)
|
ctx = super(EVEAPICorporationView, self).get_context_data(**kwargs)
|
||||||
ctx.update({
|
ctx.update({
|
||||||
'corporation': self.object,
|
'corporation': self.object,
|
||||||
'members': self.object.eveplayercharacter_set.select_related('eveaccount', 'roles').order_by('corporation_date').only('id', 'name', 'corporation_date'),
|
|
||||||
'view_members': self.object.eveplayercharacter_set.filter(eveaccount__user=self.request.user, roles__name="roleDirector").count() or self.request.user.is_superuser,
|
'view_members': self.object.eveplayercharacter_set.filter(eveaccount__user=self.request.user, roles__name="roleDirector").count() or self.request.user.is_superuser,
|
||||||
})
|
})
|
||||||
return ctx
|
return ctx
|
||||||
@@ -231,17 +234,21 @@ def eveapi_corporation_members_csv(request, corporationid):
|
|||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
class EVEAPIAllianceView(DetailView):
|
class EVEAPIAllianceView(DetailPaginationMixin, DetailView):
|
||||||
|
|
||||||
model = EVEPlayerAlliance
|
model = EVEPlayerAlliance
|
||||||
template_name= 'eve_api/alliance.html'
|
template_name= 'eve_api/alliance.html'
|
||||||
|
detail_queryset_name = 'corporations'
|
||||||
|
|
||||||
|
def get_pagination_queryset(self):
|
||||||
|
return self.object.eveplayercorporation_set.exclude(member_count=0).order_by('name')
|
||||||
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
ctx = super(EVEAPIAllianceView, self).get_context_data(**kwargs)
|
ctx = super(EVEAPIAllianceView, self).get_context_data(**kwargs)
|
||||||
ctx.update({
|
ctx.update({
|
||||||
'alliance': self.object,
|
'alliance': self.object,
|
||||||
'executor': self.object.executor.ceo_character,
|
'executor': self.object.executor.ceo_character,
|
||||||
'corporations': self.object.eveplayercorporation_set.exclude(member_count=0).order_by('name'),
|
|
||||||
})
|
})
|
||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ from django.core.exceptions import ImproperlyConfigured
|
|||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from django.views.generic.list import MultipleObjectMixin
|
from django.views.generic.list import MultipleObjectMixin
|
||||||
|
|
||||||
|
from eve_api.views.utils import DiggPaginator
|
||||||
|
|
||||||
class CSVResponseMixin(object):
|
class CSVResponseMixin(object):
|
||||||
|
|
||||||
@@ -60,3 +61,46 @@ class MultipleObjectCSVResponseMixin(CSVResponseMixin, MultipleObjectMixin):
|
|||||||
def get_csv_data(self):
|
def get_csv_data(self):
|
||||||
return self.queryset.all().values()
|
return self.queryset.all().values()
|
||||||
|
|
||||||
|
|
||||||
|
class DetailPaginationMixin(object):
|
||||||
|
|
||||||
|
detail_queryset_name = 'qs'
|
||||||
|
|
||||||
|
def paginate_queryset(self, queryset, page_size):
|
||||||
|
"""
|
||||||
|
Paginate the queryset, if needed.
|
||||||
|
"""
|
||||||
|
paginator = DiggPaginator(queryset, page_size, body=10, tail=1)
|
||||||
|
page = self.kwargs.get('page') or self.request.GET.get('page') or 1
|
||||||
|
try:
|
||||||
|
page_number = int(page)
|
||||||
|
except ValueError:
|
||||||
|
if page == 'last':
|
||||||
|
page_number = paginator.num_pages
|
||||||
|
else:
|
||||||
|
raise Http404(_(u"Page is not 'last', nor can it be converted to an int."))
|
||||||
|
try:
|
||||||
|
page = paginator.page(page_number)
|
||||||
|
return (paginator, page, page.object_list, page.has_other_pages())
|
||||||
|
except InvalidPage:
|
||||||
|
raise Http404(_(u'Invalid page (%(page_number)s)') % {
|
||||||
|
'page_number': page_number
|
||||||
|
})
|
||||||
|
|
||||||
|
def get_pagination_queryset(self):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
ctx = super(DetailPaginationMixin, self).get_context_data(**kwargs)
|
||||||
|
|
||||||
|
qs = self.get_pagination_queryset()
|
||||||
|
paginator, page, queryset, is_paginated = self.paginate_queryset(qs, 25)
|
||||||
|
|
||||||
|
ctx.update({
|
||||||
|
'paginator': paginator,
|
||||||
|
'page_obj': page,
|
||||||
|
'is_paginated': is_paginated,
|
||||||
|
self.detail_queryset_name: queryset,
|
||||||
|
})
|
||||||
|
return ctx
|
||||||
|
|
||||||
|
|||||||
278
app/eve_api/views/utils.py
Normal file
278
app/eve_api/views/utils.py
Normal file
@@ -0,0 +1,278 @@
|
|||||||
|
import math
|
||||||
|
from django.core.paginator import Paginator, QuerySetPaginator, Page, InvalidPage
|
||||||
|
|
||||||
|
__all__ = (
|
||||||
|
'InvalidPage',
|
||||||
|
'ExPaginator',
|
||||||
|
'DiggPaginator',
|
||||||
|
'QuerySetDiggPaginator',
|
||||||
|
)
|
||||||
|
|
||||||
|
class ExPaginator(Paginator):
|
||||||
|
"""Adds a ``softlimit`` option to ``page()``. If True, querying a
|
||||||
|
page number larger than max. will not fail, but instead return the
|
||||||
|
last available page.
|
||||||
|
|
||||||
|
This is useful when the data source can not provide an exact count
|
||||||
|
at all times (like some search engines), meaning the user could
|
||||||
|
possibly see links to invalid pages at some point which we wouldn't
|
||||||
|
want to fail as 404s.
|
||||||
|
|
||||||
|
>>> items = range(1, 1000)
|
||||||
|
>>> paginator = ExPaginator(items, 10)
|
||||||
|
>>> paginator.page(1000)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
InvalidPage: That page contains no results
|
||||||
|
>>> paginator.page(1000, softlimit=True)
|
||||||
|
<Page 100 of 100>
|
||||||
|
|
||||||
|
# [bug] graceful handling of non-int args
|
||||||
|
>>> paginator.page("str")
|
||||||
|
Traceback (most recent call last):
|
||||||
|
InvalidPage: That page number is not an integer
|
||||||
|
"""
|
||||||
|
def _ensure_int(self, num, e):
|
||||||
|
# see Django #7307
|
||||||
|
try:
|
||||||
|
return int(num)
|
||||||
|
except ValueError:
|
||||||
|
raise e
|
||||||
|
|
||||||
|
def page(self, number, softlimit=False):
|
||||||
|
try:
|
||||||
|
return super(ExPaginator, self).page(number)
|
||||||
|
except InvalidPage, e:
|
||||||
|
number = self._ensure_int(number, e)
|
||||||
|
if number > self.num_pages and softlimit:
|
||||||
|
return self.page(self.num_pages, softlimit=False)
|
||||||
|
else:
|
||||||
|
raise e
|
||||||
|
|
||||||
|
class DiggPaginator(ExPaginator):
|
||||||
|
"""
|
||||||
|
Based on Django's default paginator, it adds "Digg-style" page ranges
|
||||||
|
with a leading block of pages, an optional middle block, and another
|
||||||
|
block at the end of the page range. They are available as attributes
|
||||||
|
on the page:
|
||||||
|
|
||||||
|
{# with: page = digg_paginator.page(1) #}
|
||||||
|
{% for num in page.leading_range %} ...
|
||||||
|
{% for num in page.main_range %} ...
|
||||||
|
{% for num in page.trailing_range %} ...
|
||||||
|
|
||||||
|
Additionally, ``page_range`` contains a nun-numeric ``False`` element
|
||||||
|
for every transition between two ranges.
|
||||||
|
|
||||||
|
{% for num in page.page_range %}
|
||||||
|
{% if not num %} ... {# literally output dots #}
|
||||||
|
{% else %}{{ num }}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
Additional arguments passed to the constructor allow customization of
|
||||||
|
how those bocks are constructed:
|
||||||
|
|
||||||
|
body=5, tail=2
|
||||||
|
|
||||||
|
[1] 2 3 4 5 ... 91 92
|
||||||
|
|_________| |___|
|
||||||
|
body tail
|
||||||
|
|_____|
|
||||||
|
margin
|
||||||
|
|
||||||
|
body=5, tail=2, padding=2
|
||||||
|
|
||||||
|
1 2 ... 6 7 [8] 9 10 ... 91 92
|
||||||
|
|_| |__|
|
||||||
|
^padding^
|
||||||
|
|_| |__________| |___|
|
||||||
|
tail body tail
|
||||||
|
|
||||||
|
``margin`` is the minimum number of pages required between two ranges; if
|
||||||
|
there are less, they are combined into one.
|
||||||
|
|
||||||
|
When ``align_left`` is set to ``True``, the paginator operates in a
|
||||||
|
special mode that always skips the right tail, e.g. does not display the
|
||||||
|
end block unless necessary. This is useful for situations in which the
|
||||||
|
exact number of items/pages is not actually known.
|
||||||
|
|
||||||
|
# odd body length
|
||||||
|
>>> print DiggPaginator(range(1,1000), 10, body=5).page(1)
|
||||||
|
1 2 3 4 5 ... 99 100
|
||||||
|
>>> print DiggPaginator(range(1,1000), 10, body=5).page(100)
|
||||||
|
1 2 ... 96 97 98 99 100
|
||||||
|
|
||||||
|
# even body length
|
||||||
|
>>> print DiggPaginator(range(1,1000), 10, body=6).page(1)
|
||||||
|
1 2 3 4 5 6 ... 99 100
|
||||||
|
>>> print DiggPaginator(range(1,1000), 10, body=6).page(100)
|
||||||
|
1 2 ... 95 96 97 98 99 100
|
||||||
|
|
||||||
|
# leading range and main range are combined when close; note how
|
||||||
|
# we have varying body and padding values, and their effect.
|
||||||
|
>>> print DiggPaginator(range(1,1000), 10, body=5, padding=2, margin=2).page(3)
|
||||||
|
1 2 3 4 5 ... 99 100
|
||||||
|
>>> print DiggPaginator(range(1,1000), 10, body=6, padding=2, margin=2).page(4)
|
||||||
|
1 2 3 4 5 6 ... 99 100
|
||||||
|
>>> print DiggPaginator(range(1,1000), 10, body=5, padding=1, margin=2).page(6)
|
||||||
|
1 2 3 4 5 6 7 ... 99 100
|
||||||
|
>>> print DiggPaginator(range(1,1000), 10, body=5, padding=2, margin=2).page(7)
|
||||||
|
1 2 ... 5 6 7 8 9 ... 99 100
|
||||||
|
>>> print DiggPaginator(range(1,1000), 10, body=5, padding=1, margin=2).page(7)
|
||||||
|
1 2 ... 5 6 7 8 9 ... 99 100
|
||||||
|
|
||||||
|
# the trailing range works the same
|
||||||
|
>>> print DiggPaginator(range(1,1000), 10, body=5, padding=2, margin=2, ).page(98)
|
||||||
|
1 2 ... 96 97 98 99 100
|
||||||
|
>>> print DiggPaginator(range(1,1000), 10, body=6, padding=2, margin=2, ).page(97)
|
||||||
|
1 2 ... 95 96 97 98 99 100
|
||||||
|
>>> print DiggPaginator(range(1,1000), 10, body=5, padding=1, margin=2, ).page(95)
|
||||||
|
1 2 ... 94 95 96 97 98 99 100
|
||||||
|
>>> print DiggPaginator(range(1,1000), 10, body=5, padding=2, margin=2, ).page(94)
|
||||||
|
1 2 ... 92 93 94 95 96 ... 99 100
|
||||||
|
>>> print DiggPaginator(range(1,1000), 10, body=5, padding=1, margin=2, ).page(94)
|
||||||
|
1 2 ... 92 93 94 95 96 ... 99 100
|
||||||
|
|
||||||
|
# all three ranges may be combined as well
|
||||||
|
>>> print DiggPaginator(range(1,151), 10, body=6, padding=2).page(7)
|
||||||
|
1 2 3 4 5 6 7 8 9 ... 14 15
|
||||||
|
>>> print DiggPaginator(range(1,151), 10, body=6, padding=2).page(8)
|
||||||
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
||||||
|
>>> print DiggPaginator(range(1,151), 10, body=6, padding=1).page(8)
|
||||||
|
1 2 3 4 5 6 7 8 9 ... 14 15
|
||||||
|
|
||||||
|
# no leading or trailing ranges might be required if there are only
|
||||||
|
# a very small number of pages
|
||||||
|
>>> print DiggPaginator(range(1,80), 10, body=10).page(1)
|
||||||
|
1 2 3 4 5 6 7 8
|
||||||
|
>>> print DiggPaginator(range(1,80), 10, body=10).page(8)
|
||||||
|
1 2 3 4 5 6 7 8
|
||||||
|
>>> print DiggPaginator(range(1,12), 10, body=5).page(1)
|
||||||
|
1 2
|
||||||
|
|
||||||
|
# test left align mode
|
||||||
|
>>> print DiggPaginator(range(1,1000), 10, body=5, align_left=True).page(1)
|
||||||
|
1 2 3 4 5
|
||||||
|
>>> print DiggPaginator(range(1,1000), 10, body=5, align_left=True).page(50)
|
||||||
|
1 2 ... 48 49 50 51 52
|
||||||
|
>>> print DiggPaginator(range(1,1000), 10, body=5, align_left=True).page(97)
|
||||||
|
1 2 ... 95 96 97 98 99
|
||||||
|
>>> print DiggPaginator(range(1,1000), 10, body=5, align_left=True).page(100)
|
||||||
|
1 2 ... 96 97 98 99 100
|
||||||
|
|
||||||
|
# padding: default value
|
||||||
|
>>> DiggPaginator(range(1,1000), 10, body=10).padding
|
||||||
|
4
|
||||||
|
|
||||||
|
# padding: automatic reduction
|
||||||
|
>>> DiggPaginator(range(1,1000), 10, body=5).padding
|
||||||
|
2
|
||||||
|
>>> DiggPaginator(range(1,1000), 10, body=6).padding
|
||||||
|
2
|
||||||
|
|
||||||
|
# padding: sanity check
|
||||||
|
>>> DiggPaginator(range(1,1000), 10, body=5, padding=3)
|
||||||
|
Traceback (most recent call last):
|
||||||
|
ValueError: padding too large for body (max 2)
|
||||||
|
"""
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
self.body = kwargs.pop('body', 10)
|
||||||
|
self.tail = kwargs.pop('tail', 2)
|
||||||
|
self.align_left = kwargs.pop('align_left', False)
|
||||||
|
self.margin = kwargs.pop('margin', 4) # TODO: make the default relative to body?
|
||||||
|
# validate padding value
|
||||||
|
max_padding = int(math.ceil(self.body/2.0)-1)
|
||||||
|
self.padding = kwargs.pop('padding', min(4, max_padding))
|
||||||
|
if self.padding > max_padding:
|
||||||
|
raise ValueError('padding too large for body (max %d)'%max_padding)
|
||||||
|
super(DiggPaginator, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def page(self, number, *args, **kwargs):
|
||||||
|
"""Return a standard ``Page`` instance with custom, digg-specific
|
||||||
|
page ranges attached.
|
||||||
|
"""
|
||||||
|
|
||||||
|
page = super(DiggPaginator, self).page(number, *args, **kwargs)
|
||||||
|
number = int(number) # we know this will work
|
||||||
|
|
||||||
|
# easier access
|
||||||
|
num_pages, body, tail, padding, margin = \
|
||||||
|
self.num_pages, self.body, self.tail, self.padding, self.margin
|
||||||
|
|
||||||
|
# put active page in middle of main range
|
||||||
|
main_range = map(int, [
|
||||||
|
math.floor(number-body/2.0)+1, # +1 = shift odd body to right
|
||||||
|
math.floor(number+body/2.0)])
|
||||||
|
# adjust bounds
|
||||||
|
if main_range[0] < 1:
|
||||||
|
main_range = map(abs(main_range[0]-1).__add__, main_range)
|
||||||
|
if main_range[1] > num_pages:
|
||||||
|
main_range = map((num_pages-main_range[1]).__add__, main_range)
|
||||||
|
|
||||||
|
# Determine leading and trailing ranges; if possible and appropriate,
|
||||||
|
# combine them with the main range, in which case the resulting main
|
||||||
|
# block might end up considerable larger than requested. While we
|
||||||
|
# can't guarantee the exact size in those cases, we can at least try
|
||||||
|
# to come as close as possible: we can reduce the other boundary to
|
||||||
|
# max padding, instead of using half the body size, which would
|
||||||
|
# otherwise be the case. If the padding is large enough, this will
|
||||||
|
# of course have no effect.
|
||||||
|
# Example:
|
||||||
|
# total pages=100, page=4, body=5, (default padding=2)
|
||||||
|
# 1 2 3 [4] 5 6 ... 99 100
|
||||||
|
# total pages=100, page=4, body=5, padding=1
|
||||||
|
# 1 2 3 [4] 5 ... 99 100
|
||||||
|
# If it were not for this adjustment, both cases would result in the
|
||||||
|
# first output, regardless of the padding value.
|
||||||
|
if main_range[0] <= tail+margin:
|
||||||
|
leading = []
|
||||||
|
main_range = [1, max(body, min(number+padding, main_range[1]))]
|
||||||
|
main_range[0] = 1
|
||||||
|
else:
|
||||||
|
leading = range(1, tail+1)
|
||||||
|
# basically same for trailing range, but not in ``left_align`` mode
|
||||||
|
if self.align_left:
|
||||||
|
trailing = []
|
||||||
|
else:
|
||||||
|
if main_range[1] >= num_pages-(tail+margin)+1:
|
||||||
|
trailing = []
|
||||||
|
if not leading:
|
||||||
|
# ... but handle the special case of neither leading nor
|
||||||
|
# trailing ranges; otherwise, we would now modify the
|
||||||
|
# main range low bound, which we just set in the previous
|
||||||
|
# section, again.
|
||||||
|
main_range = [1, num_pages]
|
||||||
|
else:
|
||||||
|
main_range = [min(num_pages-body+1, max(number-padding, main_range[0])), num_pages]
|
||||||
|
else:
|
||||||
|
trailing = range(num_pages-tail+1, num_pages+1)
|
||||||
|
|
||||||
|
# finally, normalize values that are out of bound; this basically
|
||||||
|
# fixes all the things the above code screwed up in the simple case
|
||||||
|
# of few enough pages where one range would suffice.
|
||||||
|
main_range = [max(main_range[0], 1), min(main_range[1], num_pages)]
|
||||||
|
|
||||||
|
# make the result of our calculations available as custom ranges
|
||||||
|
# on the ``Page`` instance.
|
||||||
|
page.main_range = range(main_range[0], main_range[1]+1)
|
||||||
|
page.leading_range = leading
|
||||||
|
page.trailing_range = trailing
|
||||||
|
page.page_range = reduce(lambda x, y: x+((x and y) and [False])+y,
|
||||||
|
[page.leading_range, page.main_range, page.trailing_range])
|
||||||
|
|
||||||
|
page.__class__ = DiggPage
|
||||||
|
return page
|
||||||
|
|
||||||
|
class DiggPage(Page):
|
||||||
|
def __str__(self):
|
||||||
|
return " ... ".join(filter(None, [
|
||||||
|
" ".join(map(str, self.leading_range)),
|
||||||
|
" ".join(map(str, self.main_range)),
|
||||||
|
" ".join(map(str, self.trailing_range))]))
|
||||||
|
|
||||||
|
class QuerySetDiggPaginator(DiggPaginator, QuerySetPaginator):
|
||||||
|
pass
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import doctest
|
||||||
|
doctest.testmod()
|
||||||
Reference in New Issue
Block a user