HelloGitHub- dream chasers

The sample code in this article has been synchronously updated to the HelloGithub-Team repository

In implementing simple paging through Django Pagination, we implemented a simple paging navigation. But the effect is a little unsatisfactory, we can only click the button of the previous page and the next page to turn the page. A good Pagination effect would look something like this, but Django Pagination’s built-in API doesn’t do much for it. Next, we’ll extend Django Pagination to achieve the complete Pagination shown below.

Overview of paging Effects

A good pagination effect would have the following features, as shown in the figure above. Many web sites use similar pagination navigation.

  • Always show the first and last page.
  • The current page number is highlighted.
  • Displays several consecutive page numbers before and after the current page number.
  • If there are other page numbers between two page numbers, an ellipsis is displayed in the middle to remind the user.

Paging ideas

What would we do if we had to implement the paging effect ourselves? Let’s take a look at the components of the navigation bar. We can see that the entire paging navigation bar can be divided into seven parts:

  1. Page number of page 1, which needs to be displayed at all times.
  2. The ellipsis section after the page number on page 1. Note, however, that if the page number on page 1 follows page number 2, the ellipsis should not be displayed.
  3. The left part of the current page number, such as 3-4 here.
  4. The current page number, like 5 here.
  5. The right-hand part of the current page number, such as 6-7 here.
  6. The ellipsis before the number on the last page. Note, however, that the ellipsis should not be displayed if the page number on the last page is followed by a sequential number.
  7. The page number of the last page.

So the idea is to generate a list of page numbers in the view according to the above rules, and then loop through the list of page numbers in the template. With ideas, it is not very difficult to achieve. However, for this kind of common needs, others have already helped us to achieve good, in line with the principle of not repeating the wheel, directly use it.

First Django third-party extension: Django-pure-pagination

We first started working with Django third-party extensions. Up until then, we had been building on django’s own functionality. However, the power of Django lies in the huge number of third-party applications we have to choose from. Django can find third-party applications that someone else has already written and use them.

In fact, the correct django development posture looks something like this:

  1. Fully understand your needs and ask yourself, what would I do if I realized them myself?
  2. Research existing apps that fulfill similar needs through Google, GitHub, developer community forums, etc
  3. Use it and try to understand how others implement it

Take our paging function for example:

First we analyzed the implementation of paging requirements above. Then I did a search on GitHub using the django Pagination keyword. After comparing several projects with high star counts, I found that django-pure-Pagination documentation was the clearest and easiest to use, so I decided to integrate this application into our blog. It’s worth noting that although the application shows that the author last updated the code four years ago, I did a cursory glance at the source code and found that the Django API it relies on has been unusually stable for four years, so I made sure it would work with Django 2.2.

Let’s use it, first install it:

$ pipenv install django-pure-pagination
Copy the code

Then register it with INSTALLED_APPS:

INSTALLED_APPS = [
	#...
    'pure_pagination'.# paging

    'blog.apps.BlogConfig'.Sign up for the blog app
    'comments.apps.CommentsConfig'.Sign up for the Comments app
]
Copy the code

Modify the IndexView so that it inherits the PaginationMixin provided by Django-pure-Pagination, the mixin class that will provide the pagination mentioned above.

class IndexView(PaginationMixin, ListView):
    model = Post
    template_name = 'blog/index.html'
    context_object_name = 'post_list'
    paginate_by = 10
Copy the code

We can then configure paging in the common.py configuration, which is provided by Django-pure-pagination to personalize paging:

# Django-pure-pagination
PAGINATION_SETTINGS = {
    'PAGE_RANGE_DISPLAYED': 4.# The total number of pages that should be displayed before and after the current page (evenly distributed on both sides, so set to even),
    'MARGIN_PAGES_DISPLAYED': 2.# Number of pages displayed at the beginning and end of the page bar
    'SHOW_FIRST_PAGE_WHEN_INVALID': True.# display the first page when requested
}
Copy the code

Where pagination is needed in the template, call the render method on the page object, as in index.html:

{% if is_paginated %}
	{{ page_obj.render }}
{% endif %}
Copy the code

Note that page_obj is a paginated list of objects, as explained in the previous article. The Render method automatically renders a predefined page bar for us, and now paging is complete.

Custom Templates

Sometimes a predefined page bar doesn’t meet our needs. You can override the predefined template with a custom template. Django looks for templates by first looking at the templates root of your project configuration (the templates folder in our project), and then looking in the templates directory of your application if it doesn’t find one. Page template predefined path for pure_pagination/pagination. The HTML, so we can be in the root directory path to build a project template exactly the same as the file structure, so the django will first find our template, to our custom template, rather than the predefined templates.

Create a new pure_pagination\ directory in the Templates directory and create a pagination. HTML file.

Next is to set up paging navigation in the template, will be displayed in the seven parts of the navigation bar data, example code is as follows:

<div class="text-center pagination" style="width: 100%">
  <ul>
    {% if page_obj.has_previous %}
      <li><a href="? {{ page_obj.previous_page_number.querystring }}"
             class="prev">&lsaquo; &lsaquo;</a></li>
    {% else %}
      <li><span class="disabled prev">&lsaquo; &lsaquo;</span></li>
    {% endif %}
    {% for page in page_obj.pages %}
      {% if page %}
        {% ifequal page page_obj.number %}
          <li class="current"><a href="#">{{ page }}</a></li>
        {% else %}
          <li><a href="? {{ page.querystring }}" class="page">{{ page }}</a></li>
        {% endifequal %}
      {% else %}
        ...
      {% endif %}
    {% endfor %}
    {% if page_obj.has_next %}
      <li><a href="? {{ page_obj.next_page_number.querystring }}" class="next">&rsaquo; &rsaquo;</a>
      </li>
    {% else %}
      <li><span class="disabled next">&rsaquo; &rsaquo;</span></li>
    {% endif %}
  </ul>
</div>
Copy the code

Add a few more articles and you can see the paging effect in the example. To make paging navigation more aesthetically pleasing, set its CSS style.


“Explain Open Source Project series” — let the people who are interested in open source projects not be afraid, let the initiator of open source projects not be alone. Follow along as you discover the joys of programming, use, and how easy it is to get involved in open source projects. Welcome to leave a message to contact us, join us, let more people fall in love with open source, contribute to open source ~