How to Add Search Functionality to a Website in Django



Python


In this article, we show how to add search functionality to a website in Django.

With search functionality added to a website, a user can search any database table on the website. This can be a database of products, such as the search field that amazon has on its site. This can be a search field for posts, such as the search field on quora. Etc.

The search engine is geared toward looking up items in a database and returning results based on a user's query.

So you can either place the search functionality within an existing app, or you can create your own app entirely for search. We take the latter approach in this article and create our own search app.

We do this with the following line shown below.



So now we have an entire app for search specifically.

I do realize that most websites show a search bar on practically every page of the site. However, we will start this project by having a page specifically for search. It's then easy to implement it on multiple pages by just copying the search form to every other page.

So, since you've created an app, you have to go to the settings.py file and add the app to the INSTALLED_APPS list.

And since this app will render out a template, we need to add a template path, search/search.html

Once this is done, we can now create multiple pages that are needed for this search functionality to be implemented.

urls.py File

So the first thing is let's just create our url.

And it will be really basic.

In the urls.py file in the root project directory, we have the following code.



The above code is the code in the urls.py file in the project root directory.

Next we need to create the code for the urls.py file in the search app. This is shown below.



So basically we just want the search page to be created on the URL, http://localhost/search

A user going to this page and typing in a search and pressing the submit button will trigger the searchposts function in the views.py file.

models.py File

We are going to be performing searches from the Post database.

Let's say we have a site of posts. Users can make all types of posts, such as in quora.

The posts that users publish are obviously stored in a database and this database is Post.

Just to show you the fields of the Post database, I show the entire model below in the models.py file.



So you see we have the following fields: title, slug, content, pub_date, last_edited, author, likes and dislikes.

For this search, we are only going to search and return posts by the title and content fields.

template file

Next, we show the template file that contains the search form.

This is shown below.



So we have a search form whose attribute, action, is equal to {% url 'search:searchposts' %}

We are using the dynamic URL to trigger the function-based view, searchposts.

The method is "GET". You do not have to specify, method="GET", because the method is GET by default. However, just to be completely explicit, we do so.

Inside of the HTML form tags, we place in a search field. The field is of type, "text", because the user types in text. The name will have a value of "q". The value will be equal to, {{request.GET.q}}. This way, the query that the user enters into the field will be retained. We then just add a placeholder, which says, "Search posts"

We then add a submit button with a name of "submit" and a value of "Search"

We then close the form element.

When the page first loads, we don't want it to say, "No search queries found" because the user hasn't entered anything yet. When the page first loads, the script does not know whether the user has tried entering a query or not. To make it know, we can check to see whether the submit button was clicked.

If the submit button was clicked, it would be equal to the value of "Search"

Another thing to consider is the fact that if a user presses the submit button without entering anything, in Django, all the rows of the database table are returned. This is not what we want. Therefore we want to make sure that this doesn't happen. So we create an if statement, {% if submitbutton == 'Search' and request.GET.q != '' %}

This checks to see that the submit button was, in fact, clicked and the field isn't empty.

If the submit button wasn't clicked or the field is empty, then the else conditional will be executed.

If the submit button is clicked and the field is not empty, then we check to see if any results are matched. If any results are matched, then we output the title and content of the post. Else, we output, No search results for this query

So this is the templates file.

views.py File

Lastly, we have the views.py file.

In the views.py file, we have the functionality behind the searches of our site.

Below is the content of the views.py file.



So in our views.py file, we must import render, because we're rendering a template.

Since we are using Q objects in order to search multiple columns of the database table (the title and the content)< we must import Q.

We then must import our Post model from the posts app. This is the model we're going to be searching and returning results from.

We then create a function-based view, searchposts.

If the request.method is a GET method, then we create a variable, query, that gets the value from the search field.

We then get the value of the submit button.

If the query is not None, then we create a variable, lookups, and set it to, Q(title__icontains=query) | Q(content__icontains=query)

This checks to see if there is any title or content that contains the query that the user entered.

We then create a variable, results, that checks to see if there is any title or content that contains the query that the user entered.

When you have Q objects that are searching multiple columns of a database table, you should always use the distinct() function at the end of the results. This is because if you don't, you may get duplicates. This is because each Q object is treated separately, so that if a title and content both contain the query, each can be returned (even though they're the same object).

We then pass the results and submitbutton into the context dictionary.

Else, we just return the search template file.

And this is how we can add search functionality to a website in Django.


Related Resources

How to Randomly Select From or Shuffle a List in Python



HTML Comment Box is loading comments...