Adding a search feature to your web application lets your users navigate it easily by searching for what they want. Django provides built-in support for building a search feature by using its powerful ORM and query tools. With Django, you can implement different types of searches, including keyword searches, simple searches, and advanced searches with filters.

Implementing Search Functionality in Django

Django allows you to implement different types of searches with its built-in methods and functions. You can implement a simple keyword search or an advanced search based on your use case. You should implement an advanced search if you have a complex application, such as an e-commerce website, while a simple keyword search is suitable for less complex projects.

The code used in this article can be found on GitHub and is free for you to use under the MIT license.

Implement a Simple Keyword Search in Django

To create a simple search feature, you should start by building your search bar. You can build your search bar in your navbar. Bootstrap provides a ready-made navbar with a search bar, and you can easily integrate Bootstrap and its components into your Django project. Create your search bar in an HTML file, set the form method to POST, and give the input field a name attribute like this:

        <form class="d-flex" role="search" method="POST">
 {% csrf_token %}
 <input
    class="form-control me-2"
    type="search"
    placeholder="Search"
    name="search_query"
    required aria-label="Search"
 >
 <button class="btn btn-outline-success" type="submit">Search</button>
</form>

In the above code, the name of the input field is search_query. The form makes use of Django's CSRF token to prevent CSRF attacks. To make your search bar work, follow these steps.

  • Open your views.py file and import your model from the models.py file:
        from .models import ModelName
  • Create a view function for the search feature:
        def search_feature(request):
    # Check if the request is a post request.
    if request.method == 'POST':
        # Retrieve the search query entered by the user
        search_query = request.POST['search_query']
        # Filter your model by the search query
        posts = Model.objects.filter(fieldName__contains=search_query)
        return render(request, 'app/template_name.html', {'query':search_query, 'posts':posts})
    else:
        return render(request, 'app/template_name.html',{})

The above function first checks if the client is sending a POST request. If the check passes, it goes ahead to retrieve the value of the user’s search query like this:

        search_query = request.POST['search_query']

In request.POST[’search_query’], ‘search_query’ should be replaced with the name of your search bar’s input field.

After retrieving the value of the user’s search query, the function filters the model with it by using the __contains method. The __contains method is case-insensitive. To use this method, you should follow this format:

        fieldName__contains

For example, if you want your users to search based on a model field called name, you should modify your code to look like this:

        name__contains=search_query

Finally, the function renders a template and passes the search query and filtered model as context.

However, if the form’s method is not a POST request, the function renders a template with an empty dictionary and does not process the search query.

Create a Template for the Search Result

  • Create an HTML file to return your search results to the client side.
a folder showing four HTML files including a file called search_post.html
  • Output the search result on the page for the user to see. The code in your HTML file should look like this:
        {% if query %}
    <div>
        <div>
        <!-- loop through search query -->
        {% for post in posts %}
            <div>
                <!-- return search query -->
                <p>{{post.title}}</p>
            </div>
        {% endfor %}
        </div>
    </div>
{% else %}
    <!-- return a message if the user does not enter a search query -->
    <h1>Please enter a search query</h1>
{% endif %}

The above HTML template checks if the user enters a search query in the search bar. If the user enters a search query, a for loop loops over the search results and returns them to the user. When there is no search query, a message is displayed for the user to enter a search query. A case where there might be no search query is if your user goes directly to the URL without filling in the search bar, i.e., your user enters a URL such as mywebsite.com/search directly into the browser. You should ensure that you use Django's template inheritance in your HTML file.

a blog page showing some results after a user searched for pt
  • Modify your HTML code to return an error message if there is no search result.
        {% if query %}
    <div>
        <div>
        <!-- check if there is a result in the database-->
        {% if posts %}
            <!-- loop through search query if there is a result -->
            {% for post in posts %}
                <div>
                    <!-- return search query -->
                    <p>{{post.title}}</p>
                </div>
            {% endfor %}
            <!-- return a message if there are no results found. -->
        {% else %}
            <h3>No search results found</h3>
        {% endif %}
        </div>
    </div>
{% else %}
    <h1>Please enter a search query</h1>
{% endif %}

The new HTML template allows for a better user experience. It introduces a conditional statement to check if a search result is available in the database. If there is, it displays the search result; otherwise, it sends the user an error message.

a search page telling the user there is no result for their search

Configure Your URL Patterns

  • If you haven’t done this, create a urls.py file in your app directory.
  • In your urls.py, file create a URL pattern for your search page:
        from django.urls import path
from . import views

urlpatterns = [
    path('search/', views.search_feature, name='search-view'),
]

The program above first imports the path function and the views file related to the app. Then it creates a path named search-view for the search page.

  • Add a form action to your search bar. The action URL should point to the URL path dedicated to the search view. In this case, the form points to search-view.
        <form class="d-flex" role="search" method="POST" action="{% url 'search-view' %}">
   <input
       class="form-control me-2"
       type="search"
       placeholder="Search for something"
       name="search_query"
       required aria-label="Search"
   >
   <button class="btn btn-outline-success" type="submit">Search</button>
</form>

Without a form action pointing to your search URL path, your search feature will not work. Remember that your search URL path must point to the Django view that handles the logic of your search feature.

Create a Search Feature for Multiple Model Fields

If you want to improve the user experience of your web app, you can let your users search by more than one field in your model. For instance, in a blog app, you might want your user to search based on post titles or author names.

To implement this feature, you should use the Q object provided by Django. You should import the Q object in your views.py file like this:

        from django.db.models import Q

After importing Q, you should modify your view function like this:

        def search_post(request):
    if request.method == 'POST':
        search_query = request.POST['search_query']
        posts = Post.objects.filter(Q(title__icontains=search_query) | Q(author__icontains=search_query))
        return render(request, 'app/template_name.html', {'query':search_query, 'posts':posts})
    else:
        return render(request, 'app/template_name.html',{})

In the program above, the posts variable filters the model by either the post title or the author’s name. The function uses the OR operator—in this case, a pipe symbol—to perform the filter.

Improving User Experience With a Search Feature

A search feature in your web application effectively improves its user experience and overall usability. With Django, you only need to leverage the built-in functionalities to make your search feature work, providing significant benefits for you and your users.