This is part of our Flask series:
- Build Website with Flask β Part 1
- Build Website with Flask β Part 2
- Build Website with Flask – Part 3
- Build Website with Flask – Part 4
- Build Website with Flask – Part 5
- Build Website with Flask – Part 6
- Build Website with Flask – Part 7
- Build Website with Flask – Part 8
Story: Assume you work in the IT Department of Right-On Realtors. Your boss asks you to create a simple website the Realtors can query to view current Home Sales.
He would like this website created using the Flask plugin.
What is Flask?
Flask is a web app framework created with ease of use in mind. Without much training, you can easily create a simple web application. Flask works with Bootstrap, HTML, CSS, and Jinja (to name a few) to create a website.
Preparation
This article assumes you have completed the following from Part 1, Part 2, Part 3, Part 4, and Part 5:
- Created and Activated a Virtual Environment.
- Installed all of the required plugins.
- Created the appropriate folder structure.
- Created and saved an app.py file to the
realtors
folder.
ο»Ώ - Added Routes to the app.py file.
- Added Jinja to the
base template
. - Created and saved HTML files to the
realtors/templates
folder.
ο»Ώ - Linked to Bootstrap.
- Added a Bootstrap Navbar to the
base template
file (base.html). - Added Jinja to the HTML pages.
- Viewed the website in a Browser.
- Added a Form with elements to an HTML page.
- Added Jinja to the Reports page.
- Added code to
app.py
to get the HTML Form working.
- Read in the Real Estate CSV file to a DataFrame.
- Queried the results based on a Zip Code.
- Displayed the results on the Reports page.
In Part 6, you will learn how to:
- Validate the Zip Code.
- Clean-Up the Data.
- Correct the Sales Prices.
- Format the Sales Prices.
- Update the Navbar.
Add the following code to the top of each code snippet. This snippet will allow the code in this article to run error-free.
import pandas as pd from flask import Flask, render_template, request
Validate the Zip Code
If you enter an invalid Zip Code on the Home
page (index.html
), the Reports
page displays only the header row (column names) of the DataFrame. Let’s modify the code to correct this issue.
The options are:
- Redirect them back to the
Home
page (index.html
) with no error message, or - Redirect them back to the
Home
page (index.html
) with an error message, or - Display an error message on the
Reports
page (reports.html
) with aBack
hyperlink to return to theHome
page (index.html
).
For this example, option three (3) is on point with our tutorial.
Add the lines highlighted in yellow, indent as needed, and save.
{% extends 'base.html' %} {% block content %} <div class='container'> <h2>Real Estate Transactions</h2> <h3>{{ zip_code }}</h3> <br/><br/> {% if myData.empty %} <h4>No matching entries found!</h4> <br/><br/> <a class="nav-link" aria-current="page" href="{{ url_for('index') }}">Home</a> {% else %} <table width="600"> <thead> <tr> {% for column in myData.columns %} <th>{{column}}</th> {% endfor -%} </tr> </thead> <tbody> {% for key,value in myData.iterrows() %} <tr id="row-{{key}}"> {% for v in value.values %} <td>{{ v }}</td> {% endfor %} </tr> {% endfor %} </tbody> </table> {% endif %} </div> {% endblock %}
- Line [1] checks to see if the DataFrame contains data. For example, if the
Zip Code
entered on theHome
page (index.html
) returned results. - Line [2] executes if there are no matches. A message displays on the
Reports
page (reports.html
) indicating the same. - Line [3] places two (2) new lines after the message.
- Line [4] contains a hyperlink that, when clicked, returns the user to the
Home
page (index.html
).
The remainder of the code stays the same. However, now it resides inside an else
statement. This section executes only if the DataFrame contains results.
Let’s test this!
Navigate to the Home
page (index.html
), enter 90210 and click the Search
button. The output should display as follows.
Now let’s enter a Zip Code
that does exist, 95842. Repeat the steps above. The output should display as follows:
Excellent!
Clean-Up the Data
Upon reviewing the data, you know your boss would not like the data in uppercase. Let’s correct this by changing the case for the street,
and city
columns.
Add the lines highlighted in yellow and save.
app = Flask(__name__) @app.route('/') # home def index(): return render_template('index.html') @app.route('/reports', methods=['POST']) # reports def reports(): cols = ['street', 'city', 'zip', 'beds', 'baths', 'sq__ft', 'price'] zip_code = request.form.get('zip_code', type=int) myData = (pd.read_csv('real-estate.csv', usecols=cols)[lambda x: x['zip'] == zip_code]) myData['street'] = myData['street'].apply(lambda x: x.title()) myData['city'] = myData['city'].apply(lambda x: x.title()) return render_template('reports.html', zip_code=zip_code, myData=myData) @app.route('/contact') # contact def contact(): return render_template('contact.html')
Line [1] and Line [2] does the following:
- References the DataFrame column to modify.
- Applies
lambda
to modify each column entry to Title Case. - Saves the updated entries to the referenced DataFrame column.
Let’s run the code. Enter 95842 and click the Search
button. The output should display as follows:
Much better!
Correct the Sales Prices
The price
column appears to be missing a zero (0) at the end of each entry. These prices are too low for the Sacramento area!
Add the line highlighted in yellow and save.
app = Flask(__name__) @app.route('/') # home def index(): return render_template('index.html') @app.route('/reports', methods=['POST']) # reports def reports(): cols = ['street', 'city', 'zip', 'beds', 'baths', 'sq__ft', 'price'] zip_code = request.form.get('zip_code', type=int) myData = (pd.read_csv('real-estate.csv', usecols=cols)[lambda x: x['zip'] == zip_code]) myData['street'] = myData['street'].apply(lambda x: x.title()) myData['city'] = myData['city'].apply(lambda x: x.title()) myData['price'] = myData['price'].apply(lambda x: x*100) return render_template('reports.html', zip_code=zip_code, myData=myData) @app.route('/contact') # contact def contact(): return render_template('contact.html')
By applying a lambda
each price
is multiplied by 100.
Next, run the code and view the changes.
The output should display as follows:
Looking good!
Format the Sales Prices
The report would look better if the price
column had a currency symbol, comma separator, and decimal place. Let’s correct this.
Add the line highlighted in yellow and save.
app = Flask(__name__) @app.route('/') # home def index(): return render_template('index.html') @app.route('/reports', methods=['POST']) # reports def reports(): cols = ['street', 'city', 'zip', 'beds', 'baths', 'sq__ft', 'price'] zip_code = request.form.get('zip_code', type=int) myData = (pd.read_csv('real-estate.csv', usecols=cols)[lambda x: x['zip'] == zip_code]) myData['street'] = myData['street'].apply(lambda x: x.title()) myData['city'] = myData['city'].apply(lambda x: x.title()) myData['price'] = myData['price'].apply(lambda x: x*100).apply(lambda x: f"${x:,.2f}") return render_template('reports.html', zip_code=zip_code, myData=myData) @app.route('/contact') # contact def contact(): return render_template('contact.html')
By using a lambda
, each price
entry is formatted.
Run the code to view the new price
format.
The output should display as follows:
Update the Navbar
After reviewing the code, you notice that the Navbar
contains the Reports
menu item. It turns out we don’t need that item. Let’s remove it.
Navigate to and open the base.html
file. Remove the <li></li>
tags shown below.
Save and run.
<li class="nav-item"> <a class="nav-link" href="{{ url_for('reports') }}">Reports</a> </li>
If successful, the Navbar
should be as follows:
π‘ Note: To view any changes, Flask needs to be re-started. To perform this task, navigate to the command prompt and enter CTRL+C (stop), then flask run (re-start).
Summary
In this article, you learned how to:
- Validate the Zip Code.
- Clean-Up the Data.
- Correct the Sales Prices.
- Format the Sales Prices.
- Update the Navbar.
What’s Next
In Part 7 of this series, we will:
- Add a Stylesheet.
- Apply styles to the Navbar.
- Apply styles to the HTML pages.