Make a Flask App with a NoSQL Database Using Firebase
Yes, I love Flask quiz apps that tell me which character from The Office I am, but sometimes I just want to store some data in a database! For example, I might want to keep track of all my favorite restaurants in Southern California.
In this tutorial, we’ll learn how to do exactly that, using one of the least painful databases compatible with Flask apps: Firebase, a NoSQL database for web and mobile applications.
Note: This tutorial assumes some knowledge of Python and Flask, but you can still follow along by copy-pasting even if you are not very familiar with Flask! You can get acquainted with Flask here.
Setting up our database
First, head over to Firebase.com and make an account using your Google account.
Create a new project and name it whatever you want.
You can choose whether or not to include Google Analytics. Press the “Create Project” button and watch the magic happen!
Now, let’s create a new database for our project. Navigate to the “Database” section of the sidebar and then press “Create database.”
We’ll start in test mode for now.
Press “Next.” On the next screen, select any location and then press “Done” to create your database!
Now, change your database from Cloud Firestore database to a Realtime Database.
Now, we’re ready to fill out database with data! The Realtime Database option allows us to essentially create a database that is one giant JSON document.
Click on the plus sign next to your database name (after it says “null”) to start adding information to your database. Since my database will hold restaurants, the first key (name) in my enormous JSON document will be “restaurants.”
I’ll write “restaurants” as a name, but leave the value blank, since I want to create a list of restaurants — not just list a single restaurant. I’ll click the plus sign after “restaurants” to start making a list.
The next level down, I’ll start naming each restaurant entry with a number, as though creating a Python list where every element has an index number. I’ll name the first restaurant 0, as the first item in the list, and then press the plus sign again without creating a value.
Then, one more level down, I can finally start filling in keys (names) AND values. Restaurant name: Maria’s. Address: 11723 Barrington Ct…
When I hit the plus sign after “restaurants” again, I can add another restaurant. I’ll name this second restaurant 1, as the second item in the list, and add the name and address of another restaurant.
Add as many restaurants or items as you would like to populate your list! Don’t forget to press “Add” when you’re done.
Finally, we have to make sure we’ll be able to read and write to this database from our Flask app.
Navigate to “Rules” in the database menu and then change both occurrences of “false” in the rules to “true.”
Make sure to publish the new changes by hitting the “Publish” button.
Now we’re ready to start integrating this database into a real-life app!
Integrating the database into a Flask app
First, remix this Flask starter code on Glitch.
In the file tree on the left hand side of the screen, head over to requirements.txt. We’re already requiring Flask, but there’s a few more things to add to integrate Firebase. Add this requirements to requirements.txt:
requests
python-firebase
These requirements allow us to use Firebase in our Python-based app and also to make requests to the database.
Now, let’s go to the heart of our Flask app: server.py.
Add this line to your imports:
from firebase import firebase
This line allows us to use Firebase in server.py. Now, outside of any routes, define what Firebase is:
firebase = firebase.FirebaseApplication('YOUR_FIREBASEIO_URL', None)
How do you find your Firebaseio URL? Head over to your Database section and you should see it at the top.
The “None” in our initialization of the firebase
variable means that we haven’t defined any authentication for our database yet.
Now, in the home route ("/"
), let’s load in the some of the data! If your collection is not named restaurants, change the following code accordingly to suit your purposes:
@app.route("/")
def home():
result = firebase.get('/restaurants', None)
return str(result)
Essentially, we’re telling Firebase to get JSON content named “restaurants” (with no authentication). Then we’re stringifying all the data, just so we can see it on the page.
Let’s check it out:
Here we see a stringified list of dictionaries, one dictionary for each restaurant!
Using our knowledge of Python data structures, we can format this information in an HTML template.
Formatting the data
Our Flask app is not super pretty right now — it just shows the raw data on the screen, in 12pt Times New Roman font. We can do better than this!
At the top of server.py, import the functionality to render HTML templates by adding render_template
as an import:
from flask import Flask, render_template
In the home route, change the return statement so that it renders a template
return render_template("index.html", places=result)
Now, our Flask app will render index.html to show our data, and we’re passing the result of our database request to a variable called places
that we can then use on the HTML page.
Open the index.html file inside the templates folder. We can use Jinja templating to iterate over the places
data and print out all our favorite restaurants:
{% for p in places %} <h2> {{ places[p]["name"] }} </h2> <h3> {{ places[p]["address"] }} </h3>{% endfor %}
What’s going on here? We’re looping through all the different restaurants, which we previously gave numbers like 0, 1, 2 to simulate a list. Then, for each restaurant, we print the name as a secondary header, and the address as a smaller, tertiary header.
Now the data should appear on your website!
Extension: CSS styling
OK, so our website is awesome but still not that attractive. Your next challenge is to add a static/style.css file and then hook it up to your HTML page with the following tag:
<link rel="stylesheet" type="text/css" href="static/style.css">
Then, dive into your style.css and make your website beautiful with CSS!
Extension: User Submissions
Of course, the magic of a database is not just adding information on the Firebase interface itself, but also allowing users to contribute data!
You can add a form for user submissions on your index.html template:
<h2> Submit your favorite restaurant! </h2>
<form method="post" action="/submit">
<p>Name: <input type="text" name="name"></p>
<p>Address: <input type="text" name="address"></p>
<p><input type="submit"></p>
</form>
And then add a /submit
route to server.py to add this information to the database. But first, update the imports:
from flask import Flask, render_template, request
And then code the route:
@app.route('/submit', methods=['GET', 'POST'])
def submit():
if request.method == 'POST' and len(dict(request.form)) > 0:
userdata = dict(request.form)
name = userdata["name"][0]
address = userdata["address"][0]
new_data = {"name": name, "address": address}
firebase.post("/restaurants", new_data)
return "Thank you!"
else:
return "Sorry, there was an error."
You can see that data is sent to the database through a POST request. You tell Firebase which part of the JSON file you want to post to (in our case, restaurants), and you send a variable that holds your new data as a dictionary.
In this case, the new_data
variable held a dictionary that we constructed after fishing the restaurant name and address out of the user submission form.
As your Flask apps get more complex, you may not want to let just any user submit just any data through a POST form and have it get automatically added to the database… but more on that next time!
Troubleshooting Strategies
Is your app being weird after you add some new data? Totally normal! The best troubleshooting strategy you can try is running “refresh” in the Glitch console.
Resources
The following resources were helpful in compiling this tutorial: