We have shown you how to use bootstrap3 and Django to create a beautiful website in the previous article Django Bootstrap3 Example. But that example does not provide two important features, one is searching and the other is search results 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 clicking the Add button. Because I add 3 user whose name contains j, so there are two pages.
- To implement user search in Django is very simple, just use the model object’s filter function like below. We will show you detailed source code later.
User.objects.filter(username__contains=user_name)
2. Paginate The Search Result List.
- As you can see in the above picture, there are two pages for the search result, each page display at most 2 user records.
- You should use Django’s 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.
- Open a terminal and cd into the example root folder.
- Run python3 manage.py shell command to enter python console window.
- Run below python command in the python console, after exercise you should know how to create Django paginator object and how to get page objects 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.
2.2.1 DjangoHelloWorld / dept_emp / urls.py
- Add a URL pattern in the urls.py file for the search user requests.
url(r'^user_search/', views.user_search, name='user_search'),
2.2.2 DjangoHelloWorld / dept_emp / views.py
- Import django.core.paginator.Paginator class, 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> ...