Best Practices for Using Flask and MongoDB
Anaiya Raisinghani, Mark Smith5 min read • Published Sep 16, 2024 • Updated Sep 16, 2024
Rate this quickstart
In this article, we will be going through some of the best practices for getting started with Flask, so you too can build complex, customizable applications – easier!
From using the right driver to encoding an ObjectID correctly in JSON, this article will set you up for success when using Flask and MongoDB. Read on to learn our suggested best practices!
One of the most crucial steps is to ensure you’re using the correct driver. You have two choices of PyMongo or Motor. Both of these are recommended and developed by MongoDB. Pick Motor if you’re building a Flask application with asyncio routes, and choose PyMongo if you are building a more traditional non-async Flask application.
To download PyMongo, just use this simple command:
1 pip install pymongo
Or you can install Motor using:
1 pip install motor
Flask is one of the most popular frameworks out there for Python developers. It integrates fantastically with MongoDB. Here are some tips and tricks to help you out when building anything from simple projects to highly complex web applications with the two platforms.
We want to keep our sensitive information properly protected when we’re using Flask. While there are various ways of doing this, let’s go over two of the most secure methods for saving your environment variables and API keys.
The first way is through the Python library
dotenv
. This will include downloading the python-dotenv
package via pip, ensuring that you’re in an activated virtual environment:1 pip install python-dotenv
From here, you’ll create a
.env
file in the root of your project directory to contain any and all environment variables, such as your MongoDB connection string:1 # MongoDB connection_string [help](https://www.mongodb.com/docs/manual/reference/connection-string/) 2 MYAPP_CONNECTION_STRING=mongodb_connection_string_here
It’s crucial to not commit this file! To ensure the file isn’t committed, you can add your
.env
file to your project’s .gitignore
file or your global .gitignore
file. Learn more about keeping your .env
file private.You can import
load_dotenv
from the dotenv
package, using from dotenv import load_dotenv
. Calling the load_dotenv
function will then copy all of the configuration from your .env
file into your Flask application's process. You can then use app.config.from_prefixed_env()
to import any environments that start with a certain prefix into your Flask application. Some sample skeleton code is shown below:1 from dotenv import load_dotenv 2 3 4 load_dotenv() 5 app = Flask(__name__) 6 app.config.from_prefixed_env(“MYAPP”) 7 client = MongoClient(app.config['CONNECTION_STRING'])
You can access your secrets using the name of the variable without the “MYAPP_” prefix. This is where the app loads configuration from any environment variables that begin with “MYAPP_”. In this case, a single configuration option is provided, CONNECTION_STRING. The
dotenv
library doesn't override any existing environment variables, so you now have the choice of storing config values in the .env
file or overriding them by setting environment variables directly.Flask's configuration is very flexible, and you can find out more about it from the official documentation.
Once you’ve properly loaded your connection string, you can add in some code in the heart of your application, which is sometimes called the
app.py
file, to properly connect to the database and collection of your choosing, or to create a database and collection in the cluster of your choice. Let’s run through how to do this step with some skeleton code:1 mongo_client = MongoClient(app.config[“CONNECTION_STRING”]) 2 3 4 # access your database and collection from Atlas 5 database = mongo_client.get_database(“anaiyamovies”) 6 collection = database.get_collection(“movies”) 7 8 9 # instantiating new object with `__name__` 10 app = Flask(__name__)
What you need to know about the code above is that it doesn’t contact MongoDB at all. It won’t try to connect to your database cluster until you modify data in your cluster or obtain some data from your cluster.
The database is named “anaiyamovies” while the collection is named “movies.”
Now, using either CRUD operations inside of our Flask application or simple MongoDB operators, we can write to our collection to add in documents, delete documents, change documents, or even update our docs!
Because PyMongo is designed to be lazy, it doesn't attempt to connect to your cluster when MongoClient is initialized. This can lead to surprising behavior when you eventually try to query your database, if it turns out that you can't connect. For this reason, it's good practice to validate your database connection when you create a MongoClient. There are various ways to check if you are properly connected to your MongoDB cluster when in the process of creating your Flask application, but one of the simplest ways is to send over a
ping
command and just check the response! Let’s go through how to do this.1 # our imports go here 2 from pymongo import MongoClient 3 app = Flask(__name__) 4 app.config.from_prefixed_env(“MYAPP”) 5 6 7 def init_mongo_client(app: Flask): 8 try: 9 connection_string = "connection string here with user + pass" 10 mongo_client = MongoClient(connection_string) 11 12 13 database = mongo_client['anaiyamovies'] 14 result = mongo_client.admin.command('ping') 15 16 if int(result.get('ok')) == 1: 17 print("Connected") 18 else: 19 raise Exception("Cluster ping returned OK != 1") 20 app.mongo_client = mongo_client 21 22 23 init_mongo_client(app)
If this function can't connect to your MongoDB cluster, this will raise an exception and fail, which is good because we want to make sure we are starting up Flask correctly. If everything's okay, it will add a
mongo_client
attribute to your Flask app that your routes can use to access your MongoDB cluster.It’s always good practice to validate your database connection when your application starts up, so that you are aware of any problems with your deployment configuration at the first opportunity.
By running a
ping
test, you can easily see if you’re properly connected to the cluster you want to work with!By default, every document contains an ObjectId which is a type unique to BSON. This means they cannot be directly converted to JSON, so we need a workaround, such as encoding them as a string.
1 from bson import json_util 2 json_util.dumps(object_with_objectid)
1 from flask import Flask, Response 2 from bson import json_util 3 from typing import Mapping, Any 4 5 from dotenv import load_dotenv 6 from pymongo import MongoClient 7 8 load_dotenv() 9 10 app = Flask(__name__) 11 app.config.from_prefixed_env("MYAPP") 12 13 def init_mongodb_client(app: Flask): 14 client = MongoClient(app.config [connection_string]) 15 app.db = client.get_database() 16 17 init_mongodb_client(app) 18 19 20 def bson_to_json(bson: Mapping[str, Any]) -> Response: 21 return Response( 22 json_util.dumps(bson), 23 content_type="application/json", 24 ) 25 26 27 @app.get("/") 28 def index(): 29 return bson_to_json(app.db.find_one())
This code will handle your ObjectIds and convert them into a string format that is easier to use and deal with in your project. Bear in mind that BSON contains other types that cannot be directly converted to JSON. You may also want to consider those when writing your Flask application.
When you’re using MongoDB, generally, it’s crucial to model your data correctly so it’s as efficient as possible when using various operations. To learn more about this, please check out our Advanced Schema Design Patterns course available in MongoDB University or our Building With Patterns series.
Hopefully, these tips and tricks are helpful for using Flask with MongoDB. Through this article, you’ve learned a variety of best practices that will set you up for success while integrating Flask with your MongoDB Atlas cluster and creating some fantastic applications.
Top Comments in Forums
There are no comments on this article yet.