#python #django #pagination
Вопрос:
Я пытаюсь создать пользовательский класс разбиения на страницы. Вот моя попытка:
class CustomPagination(PageNumberPagination):
page_item_count = 10
page = 1
def get_paginated_response(self, data):
page = self.page
next_page = None
previous_page = None
if page.has_next():
next_page = page.next_page_number()
if page.has_previous():
previous_page = page.previous_page_number()
return Response({
"page_count": page.count,
"result_count": len(data),
"next": next_page,
"previous": previous_page,
"has_next_page": page.has_next(),
"has_previous_page": page.has_previous(),
"result": data,
})
Этот код сейчас работает неправильно, и это не то, что я хочу.
Я хочу задать параметр queryset с запросом в виде page_item_count и страницы.
Я хочу вернуть что-то подобное:
return Response({
"page_count": page.count, # Page count. i.e. there are 100 items, and we show 10 per page, then it must be 10.
"result_count": len(data), # object count. i.e. 100
"next": next_page, # Next page number. It's a number like 2,3,4,5... Not a link
"previous": previous_page, # Prev page number, like 2,3,....
"has_next_page": page.has_next(), # boolean
"has_previous_page": page.has_previous(), # boolean
"result": data, # objects to be returned
})
Как я могу этого достичь?
Ответ №1:
Вот решение, которое вы ищете. Вам не нужно ничего делать в представлениях. Вы можете напрямую использовать встроенную в Django разбивку на страницы в своем шаблоне. вот ссылка
<!-- Pagination-->
<ul class="pagination justify-content-center mb-4">
{% if page_obj.has_previous %}
<li class="page-item"><a class="page-link" href="?page=1">First Page</a></li>
<li class="page-item"><a class="page-link" href="?page={{ page_obj.previous_page_number }}">← Back</a></li>
{% endif %}
{% if page_obj.has_next %}
<li class="page-item"><a class="page-link" href="?page={{ page_obj.next_page_number }}">Next Page →</a></li>
{% endif %}
{% for i in paginator.page_range %}
{% if page_obj.number == i %}
<li class="page-item"><a class="page-link" href="#!">{{ i }}</a></li>
{% elif i > page_obj.number|add:'-3' and i < page_obj.number|add:'3' %} #change number as your requirement. such as if you have 50 page and how many page number you want to show per page.
<li class="page-item"><a class="page-link" href="?page={{ i }}">{{ i }}</a></li>
{%endif%}
{% endfor %}
<li class="page-item"><a class="page-link" href="?page={{ page_obj.paginator.num_pages }}">Last Page</a></li>
</ul>
</div>
Ответ №2:
Вам не нужно использовать другое имя для атрибутов разбиения на страницы DRF:
class CustomPagination(PageNumberPagination):
page_size = 100 # this is equivalent to your 'page_item_count'
page_size_query_param = 'page_item_count' # this sets the param name for the page size
max_page_size = 1000
Чтобы переопределить разбитый на страницы ответ, вы можете:
def get_paginated_response(self, data):
"""
PageNumberPagination response override
"""
return Response(OrderedDict([
('page_count', self.get_page_size(self.request)), # total # on current page
('page_number', int(self.request.query_params.get(self.page_query_param, 1))),
('result_count', self.page.paginator.count), # total # of objects that will be paginated
('next', self.get_next_link()),
('previous', self.get_previous_link()),
('results', data)
]))
На самом деле вам не нужно добавлять логическое поле в ответ, чтобы проверить, есть ли в нем следующая страница, так как полей next
и previous
достаточно.