How and why to use .env files in your Flask applications?

If you're not sure how to manage all API keys, secrets, etc on your Flask application, this means that this article fits perfectly for your needs.
What is .env file for?
It's a text file that contains keys and values of all the environment variables required by your application. You can use it to store API keys, or other sensitive variables. It's a way more secure way to store these values than just hard code it.
For purpose of this article we will use it to connect to MySQL in a more secure way.
Project structure:
Let's assume you've just started the development and your project looks like this:
web
--__init__.py
--views.py
app.py
Usually your __init__.py file would look like this:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
#Initialization of SQLAlchemy
db = SQLAlchemy()
def create_app():
app = Flask(__name__)
#App configuration
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SECRET_KEY'] = 'mytopsecretkey'
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://username:password@localhost/dbname'
db.init_app(app)
from .views import views
app.register_blueprint(views, url_prefix='/')
return app
As you can see, the SECRET_KEY, SQLALCHEMY_TRACK_MODIFICATIONS and the database's URI are included in the code, which is not comfortable to work with and not secure on many levels.
Threats
If you're working in team, your developers will have access to the keys during their work. Also the hardcoded keys will be part of the version control and if one of the keys would change and it's a part of the several functions you will have to go throught the whole application and change it one by one.
Solution
Create an .env
file and add all keys there. Afterwards add the .env
to .gitignore
and your repository will be safe and in the future you may save a lot of time.
How to work with .env file?
First of all you have to do in this moment is install the python-dotenv
pip install python-dotenv
Then create .env file in the root directory:
web
--__init__.py
--views.py
.env
app.py
Open the file and edit it. You can move all the keys or variables you want to use globally like this:
DEBUG=False
SQLA_TRACK = False
DB_URI = 'mysql://username:password@localhost/dbname'
DB_SECRET = 'mytopsecretkey'
Save the .env
file.
Usage
Open __init__.py
and add two imports:
import os
from dotenv import load_dotenv
Then Initialize dotenv below the DB initialization:
#Initialization of dotenv module
load_dotenv()
Now you can simply use the environmental variables with os.genenv()
For example
#Old DATABASE_URI setup
app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('DB_URI')
#New DATABASE_URI setup
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://username:password@localhost/dbname'
The whole __init__.py file should looks like this:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from dotenv import load_dotenv
import os
#Initialization of SQLAlchemy
db = SQLAlchemy()
#Initialization of dotenv module
load_dotenv()
def create_app():
app = Flask(__name__)
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = os.getenv('SQLA_TRACK')
app.config['SECRET_KEY'] = os.getenv('DB_SECRET')
app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('DB_URI')
db.init_app(app)
from .views import views
app.register_blueprint(views, url_prefix='/')
return app
About Shimmy
Tech freak.
My whole career and life is orbiting the technology. Fan of automation and everything that's making your life and job easier.
I was working in different roles, from a stereotypical IT guy in the company, through IT Support, web development.