Django Filter And Pagination Example

We have show you how to use bootstrap3 and Django to create a beautiful web site in previous article Django Bootstrap3 Example. But that example do not provide two important feature, one is search and the other is result list pagination. This article will add the two features to it. All the source code is based on the previous example.

1. Add Search User By Name Function.

First let us look at the picture below to see what the function looks like. The search result has also been paginated. Each page will only show two user records. To demo the function, you need to first add more users by click the Add button. Because i add 3 user whose name contains j, so there are two pages.

django search user result list page 1

django search user result list page 2

To implement user search in Django is very simple, just use model object’s filter function like below. We will show you detail source code later.

User.objects.filter(username__contains=user_name)

2. Paginate The Result List.

As you can see in above picture, there are two pages for the search result, each page display at most 2 user records. You should use Django built-in pagination library to implement this. So you must import django.core.paginator.Paginator class to do it.

First let us implement model result list pagination in python console like below, then we can add the pagination function in the web page.

2.1 Implement Model Result Pagination In Python Console.

  1. Open a terminal and cd into the example root folder.
  2. Run python3 manage.py shell command to enter python console window.
  3. Run below python command in the python console, after exercise you should know how to create Django paginator object and how to get page object and various page properties use the function it provided.
    # import Paginator class.
    >>> from django.core.paginator import Paginator
    
    # import model object class.
    >>> from django.contrib.auth.models import User
    
    # get model data list.
    >>> user_list = User.objects.all()
    
    # create the Paginator object with the provided data list and page size.
    >>> p = Paginator(user_list, 2)
    
    # show total result list count in all pages.
    >>> p.count
    7
    
    # show page count range, totally 7 records and each page show 2 records, so there are 4 pages.
    >>> p.page_range
    range(1, 5)
    
    # get the first page object.
    >>> page1 = p.page(1)
    >>> page1
    <Page 1 of 4>
    
    # show the first page data list.
    >>> page1.object_list
    <QuerySet [<User: admin>, <User: jerry>]>
    
    # get the second page object.
    >>> page2 = p.page(2)
    >>> page2
    <Page 2 of 4>
    
    # show the second page data list.
    >>> page2.object_list
    <QuerySet [<User: kevin>, <User: tom>]>
    
    # check if current page has previous or next page.
    >>> page2.has_previous()
    True
    >>> page2.has_next()
    True
    
    # show previous, current and next page number
    >>> page2.previous_page_number()
    1
    >>> page2.number
    2
    >>> page2.next_page_number()
    3
    
    # show current page result data start and end index in all result list.
    >>> page2.start_index()
    3
    >>> page2.end_index()
    4

2.2 Add Search And Pagination Function In Web Page.

To implement this, we should change some files like below.

READ :   How To Add New Model Field To Exist Django Model

django project app dept_emp source files structure

2.2.1 DjangoHelloWorld / dept_emp / urls.py

Add a url pattern in the urls.py file for search user request.

url(r'^user_search/', views.user_search, name='user_search'),
2.2.2 DjangoHelloWorld / dept_emp / views.py

Import django.core.paginator.Paginator class and edit user_list function and add user_search, do_pagination function in views.py file.

from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger


@login_required()
def user_list(request):
    # list all users.
    user_list = User.objects.all()

    page_number = request.GET.get('page', 1)

    paginate_result = do_paginate(user_list, page_number)

    user_list = paginate_result[0]

    paginator = paginate_result[1]

    base_url = '/dept_emp/user_list/?'

    return render(request, 'dept_emp/user_list.html',
                      {'user_list': user_list, 'paginator' : paginator, 'base_url': base_url})

@login_required()
def user_search(request):
    user_name = request.POST.get('user_name', '').strip()

    if len(user_name) == 0:
        user_name = request.GET.get('user_name', '').strip()

    user_list = User.objects.filter(username__contains=user_name)

    page_number = request.GET.get('page', 1)

    paginate_result = do_paginate(user_list, page_number)

    user_list = paginate_result[0]

    paginator = paginate_result[1]

    base_url = '/dept_emp/user_search/?user_name=' + user_name + "&"

    return render(request, 'dept_emp/user_list.html',
                      {'user_list': user_list, 'paginator' : paginator, 'base_url': base_url, 'search_user_name': user_name})

def do_paginate(data_list, page_number):

    ret_data_list = data_list

    # suppose we display at most 2 records in each page.
    result_per_page = 2

    # build the paginator object.
    paginator = Paginator(data_list, result_per_page)

    try:
        # get data list for the specified page_number.
        ret_data_list = paginator.page(page_number)
    except EmptyPage:
        # get the lat page data if the page_number is bigger than last page number.
        ret_data_list = paginator.page(paginator.num_pages)
    except PageNotAnInteger:
        # if the page_number is not an integer then return the first page data.
        ret_data_list = paginator.page(1)

    return [ret_data_list, paginator]
2.2.3 DjangoHelloWorld / templates / dept_emp / user_list.html

Change the user search form html code to below.

<!-- search user -->

<div class="page-header">

   <div id="navbar" class="navbar-collapse collapse">

       <form class="navbar-form" method="post" action="{% url 'dept_emp:user_search' %}">

              <!-- avoid CSRF verification failed error. -->
              {% csrf_token %}

           <div class="form-group">

              <input name="user_name" type="text" placeholder="User Name" class="form-control" value="{{ search_user_name }}">

           </div>

           <button type="submit" class="btn btn-success">Search</button>

       </form>

   </div>

</div>

Add user list result pagination code after user list table like below.

...
<div class="pagination">


    <!-- previous page link -->

    {% if user_list.has_previous %}

        <a href="{{ base_url }}page={{ user_list.previous_page_number }}">Prev</a></li>

    {% else %}

        <span class="disabled">Prev</span>

    {% endif %}




    <!-- page number link-->

    {% for i in paginator.page_range %}

         {% if user_list.number == i %}

              <span class="active">{{ i }} <span class="sr-only">(current)</span></span>

         {% else %}

              <a href="{{ base_url }}page={{ i }}">{{ i }}</a></li>

         {% endif %}

    {% endfor %}


    <!-- next page link -->

    {% if user_list.has_next %}
 
         <a href="{{ base_url }}page={{ user_list.next_page_number }}">Next</a>

    {% else %}
 
         <span class="disabled">Next</span>
 
    {% endif %}

</div>

...

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.