
Некоторое время назад я начал делать самые разные вещи с помощью Django. Идеи, которые вы можете найти в этом блоге и на моём канале YouTube, и я понял, что нам всё ещё не хватает некоторых базовых элементов, таких как разбиение на страницы.
Чтобы выполнить разбиение на страницы в Django, мы можем использовать простой класс под названием Paginator, как показано в примерах в этой публикации. Хитрость заключается в том, что в Django есть два типа представлений: общие, для которых в данном конкретном случае используется ListView, и персонализированные представления, которые мы рассмотрим в этой статье.
Разбивка на страницы со стороны представления и шаблона
Мы будем разбивать на страницы с обеих сторон: с одной стороны — для клиента или веб-страницы, с другой — для отображения списка, в данном случае с помощью CSS и Bootstrap. Хотя вы можете использовать собственный CSS, Bulma, Tailwind или что-то ещё, с чем вы работаете.
Мы узнаем, как создать довольно универсальную и многократно используемую простую систему разбивки на страницы для нашего списка.
В наши дни это довольно распространённая практика, когда мы хотим разбить на страницы список или набор записей, например, публикации в блоге, список товаров в интернет-магазине и т. д.
Разбивка на страницы в Django в любом представлении
Следуя нашему примеру, мы создадим простую систему разбивки на страницы для комментариев. Для этого мы продолжим работу с кодом, который мы показали ранее:
Разбивка на страницы в Django
В Django есть класс Paginator, который принимает два аргумента: список всех записей и уровень разбиения на страницы, то есть, если вам нужна страница с 5 записями (размер страницы 5), 10 записями и т. д.
Как видите, мы также проверяем, что получаем параметр через get, чтобы указать, какую страницу мы хотим увидеть. В этом случае мы будем использовать параметр, который передаётся через get, под названием page, но он может иметь любое имя. Не забудьте добавить проверку, чтобы избежать проблем и обработать соответствующий диапазон:
номер_страницы = request.GET.get('страница')
Итак, с помощью класса Paginator в Django мы передаём ему список, который хотим разбить на страницы, и уровень разбивки на страницы; остальная часть кода остаётся такой же, как в предыдущей записи:
комментарии = Comment.objects.all()
пагинатор = Пагинатор(комментарии, 5) # Показывать 25 контактов на странице.
номер_страницы = запрос.GET.get('страница')
страница_комментариев = пагинатор.получить_страницу(номер_страницы)
return render(запрос, 'index.html', {'comments_page': comments_page})
Создайте ссылки для разбивки на страницы
Основной код будет точно таким же, как и в предыдущем примере, но теперь мы добавим несколько ссылок на разбиение на страницы. Как видите, для создания схемы, которую можно использовать повторно, мы включаем представление, которое является представлением ссылок на навигацию:
<тело>
{% для c в comments_page %}
<div>
<p>
{{ c.текст|escape }}
{{ c.date_posted|дата:"D d M Y" }}
</p>
</div>
{% конец для %}
{% включить "partials/pagination.html" с помощью page_obj=comments_page %}
</тело>
Build the pagination links with Bootstrap 4 or 5 layout
We are going to save the view to generate the links in the following location as you could see in the previous code:
partials/pagination.html
This view will simply receive the complete list of records that we want to paginate; the code itself is not complicated at all, just check if we have previous or subsequent links and finally iterate according to the pagination range we have to generate the pagination links:
<nav aria-label="Page navigation example">
<ul class="pagination justify-content-center mt-5">
{% if page_obj.has_previous %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.previous_page_number }}">previous</a>
</li>
{% endif %}
{% for i in page_obj.paginator.page_range %}
{% if i == page_obj.number %}
<li class="page-item active">
<a class="page-link" href="#">{{ i }}</a>
</li>
{% else %}
<li class="page-item">
<a class="page-link" href="?page={{ i }}">{{ i }}</a>
</li>
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<li class="page-item">
<a class="page-link" href="?page={{ page_obj.next_page_number }}">next</a>
</li>
{% endif %}
</ul>
</nav>
The code, although it seems complicated if you analyze it a bit, is self-explanatory, we simply want to build navigation links, we have two conditionals, at the beginning and end of the block, simply to ask if there are previous or next links to show; and in the middle, we paint all the navigation links.
Explanation of parameters used
We use several parameters in the view to build our navigation links:
- page_obj.has_previous: Boolean indicating if there is a previous page.
- page_obj.has_next: Boolean indicating if there is a next page.
- page_obj.previous_page_number: Returns the number of the previous page.
- page_obj.next_page_number: Returns the number of the next page.
- page_obj.number: Returns the number of the current page.
- page_obj.paginator.num_pages: Returns the total number of pages.
Extra: Pagination in Django with ListView
We can also use the pagination scheme using the generic views that Django offers us; specifically the generic ListView view, for lists.
We have to simply define a class that extends from ListView and specify some parameters:
- The model with which we are going to work
- The location of the template, which we can perfectly use from the previous list
- The pagination level.
In addition to this, we have to create a function called get_queryset which takes the page as a parameter and we have to return an instance of the current page.
So with this, our code looks like this:
from django.views.generic import ListView
from django.core.paginator import Paginator
class Comentarios(ListView):
model = Comment
template_name = 'index.html'
paginate_by = 3
def get_queryset(self,pag=1):
comments = Comment.objects.all()
paginacion = Paginator(comments,'cantidad objetos')
if len(paginacion.page(1)) == 0:
return None
else:
return paginacion.page(pag)
The parameter that we are going to pass to the template is called object_list, therefore, we have to change the reference in the template:
{% for c in object_list %}
Conclusions
Pagination is a scheme that we use in any modern framework like today and today it cannot be missing to be able to paginate different types of development that we want to do, either to use them in a table, or another customizable element, including a RestApi.
Of course, when Django handles different types of templates, we can define the same for each type of template, either in the use of the ListViem as a component of generic views or a view/template 100% customizable by us and everything rotating with the queryset which is our data source.
Of course, when Django handles different types of templates, we can define the same for each type of template, either in the use of the ListViem as a component of generic views or a view/template 100% customizable by us.
I agree to receive announcements of interest about this Blog.
We are going to know how we can create a paginated list of records with Django and Bootstrap 5 using the Paginator class that the framework itself offers us.
- Andrés Cruz