Going through the steps on how to build a search feature in a Python Flask app. Flask is a popular microweb framework that makes it easy to build web applications in Python. We will use Jinja2 templates to create the user interface and a search function to retrieve search results from a database.
Table of Contents
- Creating a Flask App with Search Feature
- Creating Search Template
- Creating the Results Template
- Implementing Search Function to use a Database
- Creating the Database
- Conclusion
Creating a Flask App with Search Feature
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from flask import Flask, request, render_template
app = Flask(__name__)
@app.route('/')
def search_page():
return render_template('search.html')
@app.route('/search', methods=['POST'])
def search():
query = request.form['query']
# Perform search and return results
return render_template('results.html', query=query, results=results)
if __name__ == '__main__':
app.run()
This Flask app has two routes: /
and /search
. The /
route renders the search.html
template, which should include a form with a search bar. The /search
route handles the form submission and performs the search using the query entered by the user. The search results are then passed to the results.html
template, which can display the results in a list or table format.
To use this app, we will need to create the search.html
and results.html
templates and place them in the templates
directory. We will also need to implement the search function and define the results
variable.
Creating Search Template
We need to create a template
. To do this, we need create a folder called templates
in the root directory of the flask app. Our directory should look like this:
1
2
3
4
$ tree
.
└── FlaskAppProjectFolder
└── templates
Let’s start by creating a simple HTML landing page for our search bar called search.html
and save it into the newly created templates
folder with the following code:
1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html>
<head>
<title>Search Page</title>
</head>
<body>
<h1>Search</h1>
<form action="/search" method="POST">
<input type="text" name="query" placeholder="Enter search query">
<button type="submit">Search</button>
</form>
</body>
</html>
Now our directory should look like this:
1
2
3
4
5
$ tree
.
└── FlaskAppProjectFolder
└── templates
└── search.html
If you open that HTML file in a browser of your choice, you will see the following:
This template includes a simple form with a text input field for the search query and a submit button. The form’s action is set to /search
, which is the URL that the form will submit the search query to. The method is set to POST
, which means that the search query will be sent to the server as part of the HTTP request body.
You can customize this template further by adding additional form fields or styling the form with CSS. You can also use Flask’s template inheritance feature to create a base template that includes the search form, and then extend the base template in other templates as needed.
Optional CSS for Search
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<!DOCTYPE html>
<html>
<head>
<title>Search Page</title>
<style>
form {
width: 500px;
margin: 0 auto;
text-align: center;
background-color: #eee;
padding: 20px;
border-radius: 5px;
}
input[type="text"] {
width: 70%;
padding: 12px 20px;
margin: 8px 0;
box-sizing: border-box;
border: 2px solid #ccc;
border-radius: 4px;
}
button[type="submit"] {
width: 20%;
background-color: #4CAF50;
color: white;
padding: 14px 20px;
margin: 8px 0;
border: none;
border-radius: 4px;
cursor: pointer;
}
button[type="submit"]:hover {
background-color: #45a049;
}
</style>
</head>
<body>
<h1>Search</h1>
<form action="/search" method="POST">
<input type="text" name="query" placeholder="Enter search query">
<button type="submit">Search</button>
</form>
</body>
</html>
This template includes some basic CSS styles to make the form look more visually appealing. The form has a fixed width, a centered layout, and a light grey background color. The input field and submit button have some basic styling applied to them, including a border, padding, and a hover effect for the submit button.
This is what that results of the CSS styling looks like when opening this HTML file in a browser:
Creating the Results Template
Next let’s create a search results template with the filename results.html
in the templates
folder using the following code:
1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html>
<head>
<title>Search Results</title>
</head>
<body>
<h1>Results for: </h1>
<ul>
</ul>
</body>
</html>
This template uses Jinja2 syntax to display the search results in an unordered list. The query
and results
variables are passed to the template from the search
route in the Flask app.
Now our directory should look like this:
1
2
3
4
5
6
$ tree
.
└── FlaskAppProjectFolder
└── templates
├── search.html
└── results.html
Implementing Search Function to use a Database
Now that we have a base flask app with our search and results templates created in the templates folder, we can add in the following block of code (After app = Flask(__name__)
and Before def perform_search(query):
) to implement our search function:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import sqlite3
def perform_search(query):
# Connect to the database
conn = sqlite3.connect('database')
c = conn.cursor()
# Execute the search query
c.execute("SELECT * FROM table WHERE column LIKE ?", (query,))
results = c.fetchall()
# Close the connection
conn.close()
return results
When using
sqlite3.connect()
as shown here in the code block. I have seendatabase
anddatabase.db
passed here. If you getting the following error:sqlite3.DatabaseError: file is not a database
then it will likely be resolved by dropping the.db
file extension.
This search function connects to a SQLite database, executes a search query that matches the query string against a column in a table, and returns the search results. You can customize the search query to meet the specific needs of your database and search requirements.
You will need to make sure that you have a database file named database
(or database.db
) in the same directory as your Flask app, and that you have a table with a column that you want to search. You will also need to install the sqlite3
library in order to use it in your Flask app because now we are importing sqlite3 at the beggining of our code.
Creating the Database
For this Flask app we will us the following database as an example:
1
2
3
4
5
6
7
8
9
10
CREATE TABLE users (
id INTEGER PRIMARY KEY,
username TEXT,
email TEXT
);
INSERT INTO users (username, email) VALUES
("user1", "user1@example.com"),
("user2", "user2@example.com"),
("user3", "user3@example.com");
This database file contains a table named users
with three columns: id
, username
, and email
. It also includes three rows of data for three sample users.
This database file contains only the CREATE TABLE
and INSERT INTO
statements, which define the structure of the users
table and insert data into the table. However, these statements do not create the actual database file.
To create the database file, you will need to execute these statements using a SQLite client or by using the execute()
method in your Flask app. For this example we will use the execute()
method in our Flask app to create the database file and populate the users table:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import sqlite3
def create_database():
# Connect to the database
conn = sqlite3.connect('database.db')
c = conn.cursor()
# Create the users table
c.execute(
'''CREATE TABLE users (
id INTEGER PRIMARY KEY,
username TEXT,
email TEXT
)'''
)
# Insert data into the users table
c.execute(
'''INSERT INTO users (username, email) VALUES
("user1", "user1@example.com"),
("user2", "user2@example.com"),
("user3", "user3@example.com")'''
)
# Save changes and close the connection
conn.commit()
conn.close()
create_database()
This code creates the database file for us and executes the CREATE TABLE
and INSERT INTO
statements to create the users
table and insert data into the table.
Place this block after app = Flask(__name__)
and before our recently created def perform_search(query):
lines.
Conclusion
To recap, we have created a FlaskApp.py
. Added a search function to use with a database. Added some sample data with the execute()
method to create that database. Added our search and results templates with working routes to be used in our URLs and serve up the pages.
Our Flask app directory will look like the following:
1
2
3
4
5
6
7
8
$ tree
.
└── FlaskAppProjectFolder
├── FlaskApp.py
├── database
└── templates
├── search.html
└── results.html
Completed FlaskApp.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
from flask import Flask, request, render_template
import sqlite3
app = Flask(__name__)
def create_database():
# Connect to the database
conn = sqlite3.connect('database')
c = conn.cursor()
# Create the users table
c.execute(
'''CREATE TABLE users (
id INTEGER PRIMARY KEY,
username TEXT,
email TEXT
)'''
)
# Insert data into the users table
c.execute(
'''INSERT INTO users (username, email) VALUES
("user1", "user1@example.com"),
("user2", "user2@example.com"),
("user3", "user3@example.com")'''
)
# Save changes and close the connection
conn.commit()
conn.close()
create_database()
def perform_search(query):
# Connect to the database
conn = sqlite3.connect('database')
c = conn.cursor()
# Execute the search query
c.execute("SELECT * FROM users WHERE username LIKE ?", (query,))
results = c.fetchall()
# Close the connection
conn.close()
return results
@app.route('/')
def search_page():
return render_template('search.html')
@app.route('/search', methods=['POST'])
def search():
query = request.form['query']
results = perform_search(query)
return render_template('results.html', query=query, results=results)
if __name__ == '__main__':
app.run()
Completed Search HTML Template
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<!DOCTYPE html>
<html>
<head>
<title>Search Page</title>
<style>
form {
width: 500px;
margin: 0 auto;
text-align: center;
background-color: #eee;
padding: 20px;
border-radius: 5px;
}
input[type="text"] {
width: 70%;
padding: 12px 20px;
margin: 8px 0;
box-sizing: border-box;
border: 2px solid #ccc;
border-radius: 4px;
}
button[type="submit"] {
width: 20%;
background-color: #4CAF50;
color: white;
padding: 14px 20px;
margin: 8px 0;
border: none;
border-radius: 4px;
cursor: pointer;
}
button[type="submit"]:hover {
background-color: #45a049;
}
</style>
</head>
<body>
<h1>Search</h1>
<form action="/search" method="POST">
<input type="text" name="query" placeholder="Enter search query">
<button type="submit">Search</button>
</form>
</body>
</html>
Completed Results HTML Template
1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html>
<head>
<title>Search Results</title>
</head>
<body>
<h1>Results for: </h1>
<ul>
</ul>
</body>
</html>
It Works
Searching for a user
Getting results back from database for user1