You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

75 lines
3.1 KiB

# -*- coding: utf-8 -*-
from functools import wraps
from django.conf import settings
from django.core.paginator import Paginator, InvalidPage, EmptyPage
from django import forms
from commons.utils import safe_int
# допустимые значения `per_page`
_ALLOW_PER_PAGE = (10,20,50,75,100,) # по умолчанию
ALLOW_PER_PAGE = getattr(settings, 'ALLOW_PER_PAGE', _ALLOW_PER_PAGE)
class PaginationForm(forms.Form):
"""Форма для пагинатора со списком допустимых значений `per_page`."""
per_page = forms.ChoiceField(label=u'записей на странице', choices=zip(ALLOW_PER_PAGE, ALLOW_PER_PAGE),
required=False)
def save_per_page_value(func):
"""Декоратор.
Если задан request.POST['per_page'], то сохранить его в куку.
Имя куки - per_page, срок хранения - 1 год.
"""
@wraps(func)
def wrapper(request, *args, **kwargs):
output = func(request, *args, **kwargs)
key = 'per_page'
if request.method == 'POST' and key in request.POST:
per_page = safe_int(request.POST[key])
if per_page in ALLOW_PER_PAGE:
if hasattr(output, 'set_cookie'):
max_age = 365*24*60*60 # год
output.set_cookie(key, per_page, max_age)
return output
return wrapper
def get_per_page_value(request):
"""Возвращает значение `per_page` (нужно для создания пагинатора).
Последовательно ищет `per_page` в словарях request.POST и request.COOKIES.
Если его там нет, возвращает самое первое значение из списка допустимых.
"""
per_page = None
# если задан, взять per_page из post
if request.method == 'POST' and 'per_page' in request.POST:
per_page = safe_int(request.POST.get('per_page'))
# иначе попробовать взять его из cookies
elif 'per_page' in request.COOKIES:
per_page = safe_int(request.COOKIES.get('per_page'))
# проверить чтоб значение per_page было в списке допустимых
if per_page not in ALLOW_PER_PAGE:
per_page = ALLOW_PER_PAGE[0]
return per_page
def pagination(request, object_list, page_num=None, form_class=PaginationForm):
"""Создает и возвращает объект django.core.paginator.Paginator и,
если form_class!=None, форму со списком допустимых значений `per_page`.
"""
per_page = get_per_page_value(request) # кол-во записей на странице
# пагинатор
paginator = Paginator(object_list, per_page)
page_num = max(1, safe_int(page_num, 1))
try:
objects = paginator.page(page_num)
except (EmptyPage, InvalidPage):
objects = paginator.page(paginator.num_pages)
# форма
form = None
if form_class:
form = PaginationForm(initial={'per_page': per_page,})
return objects, form