Muhammad Saim
Posted on August 22, 2021
Hello.! I hope you are doing great. In the last post we setup our application folder structure and in this one we are setting the backend for our application.
First create .env file in the root of the folder and add our environment variables to this file.
SECRET_KEY = "abcdefgh"
FLASK_APP = run.py
FLASK_ENV= development # production/development
# Define the database
# Flask-SQLAlchemy
SQLALCHEMY_DATABASE_URI = "mysql+mysqlconnector://DB_USERNAME:DB_PASSWORD@127.0.0.1:3306/DB_DATABASE"
SQLALCHEMY_TRACK_MODIFICATIONS = False
# Static Assets
STATIC_FOLDER_PATH = "/assets"
STATIC_FOLDER = "assets"
TEMPLATES_FOLDER = "views"
UPLOAD_FOLDER = "application/assets/uploads"
Now get a detailed look on the environment variables.
SECRET_KEY
A secret key that will be used for securely signing the session cookie and can be used for any other security related needs by extensions or your application.
FLASK_APP
The FLASK_APP environment variable is used to specify how to load the application.
FLASK_DEBUG
What environment the app is running in. Flask and extensions may enable behaviors based on the environment, such as enabling debug mode.
SQLALCHEMY_DATABASE_URI
The database URI that should be used for the connection.
SQLALCHEMY_TRACK_MODIFICATIONS
If set to True, Flask-SQLAlchemy will track modifications of objects and emit signals. The default is None, which enables tracking but issues a warning that it will be disabled by default in the future. This requires extra memory and should be disabled if not needed.
STATIC_FOLDER_PATH
can be used to specify a different path for the static files on the web. Defaults to the name of the STATIC_FOLDER folder.
STATIC_FOLDER
The folder with static files that is served at STATIC_FOLDER_PATH. Relative to the application root_path or an absolute path. Defaults to 'static'.
TEMPLATES_FOLDER
The folder that contains the templates that should be used by the application. Defaults to 'templates' folder in the root path of the application.
UPLOAD_FOLDER
The folder that is responsible for our file uploads.
Now open config.py and create Config class on it and add class properties which reads data from the .env.
import os
from os import environ
class Config:
# General Config
SECRET_KEY = environ.get('SECRET_KEY')
FLASK_APP = environ.get('FLASK_APP')
FLASK_DEBUG = environ.get('FLASK_DEBUG')
BASE_DIR = os.path.abspath(os.path.dirname(__file__))
# Static Assets
STATIC_FOLDER_PATH = environ.get('STATIC_FOLDER_PATH')
STATIC_FOLDER = environ.get('STATIC_FOLDER')
TEMPLATES_FOLDER = environ.get('TEMPLATES_FOLDER')
UPLOAD_FOLDER = environ.get('UPLOAD_FOLDER')
# Flask-SQLAlchemy
SQLALCHEMY_DATABASE_URI = environ.get('SQLALCHEMY_DATABASE_URI')
SQLALCHEMY_TRACK_MODIFICATIONS = bool(environ.get('SQLALCHEMY_TRACK_MODIFICATIONS'))
So in the config.py BASE_DIR is use to store the root path of the application folder for use in the future.
Now open application/init.py file and start the configuring application. First import the required modules.
from dotenv import load_dotenv
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import MetaData
after that load the ENV variables
load_dotenv()
Now set the database constraints names for forigen keys, primary keys and other constrants. Make a dictionary of python.
convention = {
"ix": 'ix_%(column_0_label)s',
"uq": "uq_%(table_name)s_%(column_0_name)s",
"ck": "ck_%(table_name)s_%(column_0_name)s",
"fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
"pk": "pk_%(table_name)s"
}
metadata = MetaData(naming_convention=convention)
After that initialize the SQLAlchemy and the Migrate objects.
db = SQLAlchemy(metadata=metadata)
migrate = Migrate()
So at this time our init.py file looks like this.
from dotenv import load_dotenv
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import MetaData
from flask_debugtoolbar import DebugToolbarExtension
load_dotenv()
convention = {
"ix": 'ix_%(column_0_label)s',
"uq": "uq_%(table_name)s_%(column_0_name)s",
"ck": "ck_%(table_name)s_%(column_0_name)s",
"fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
"pk": "pk_%(table_name)s"
}
metadata = MetaData(naming_convention=convention)
db = SQLAlchemy(metadata=metadata)
migrate = Migrate()
Now open a application/settings.py file and import the moduels.
from flask import Flask
import os
import config
from application import (
db,
migrate
)
So we create init.py in our application folder so this will make application a python package so in the last we use from statement with application and which db or migrate objects we created in the init.py so we are now importing from the applictaion.
Create a home.py file in our controllers folder and use flask blueprint to create a blueprint for our first route.
from flask import Blueprint, render_template
controller = Blueprint('home', __name__)
@controller.route('/', methods=['GET'])
def index():
return "Home Controller"
Now Create a user.py file in models folder to create our first model. This will be SQLAlchemy model and also uses for our migartions also.
User class will be extend with db.Model and here we have a special property name __ tablename __ which is use to change the tablename otherwise without __ tablename __ table name will be the class name.
from application import db
class User(db.Model):
__tablename__ = 'users'
id = db.Column(
db.Integer,
primary_key=True
)
name = db.Column(
db.String(255),
nullable=False
)
email = db.Column(
db.String(255),
unique=True,
nullable=False
)
password = db.Column(
db.String(255),
nullable=False
)
role = db.Column(
db.String(50),
nullable=False,
server_default="user"
)
created_at = db.Column(
db.DateTime,
server_default=db.func.now(),
nullable=False
)
updated_at = db.Column(
db.DateTime,
server_default=db.func.now(),
nullable=False
)
So Now we have our controller and the model so we can now register those in our applciation.
Now open settings.py and create three functions in the file first one will be the register_blueprints, import_models and initialize_plugins.
In the register_blueprints function import the controller from the controllers and register that controller.
def register_blueprints(app):
from application.controllers import (
home
)
app.register_blueprint(home.controller)
In the import_models function import the models from the Models and register them in this function.
def import_models():
# import database models
from application.models import (
user
)
Last but not least we have a initialize_plugins which is used for initialize the flask apps to the flask like SQLAlchemy, Flask Migrate etc.
Now its time to create the our last function in this file which will be the initialize_flask_app which is responsible to initialize the flask app with configurations which we added in our config.py.
def initialize_flask_app():
# Initialize the core application.
app = Flask(
__name__,
instance_relative_config=False,
template_folder=config.Config.TEMPLATES_FOLDER,
static_folder=config.Config.STATIC_FOLDER,
static_url_path=config.Config.STATIC_FOLDER_PATH
)
app.config.from_object('config.Config')
return app
instance_relative_config
if set to True relative filenames for loading the config are assumed to be relative to the instance path instead of the application root.
So here I set it to False so we can load our own configs from our own location so at the 2nd last line we set flask app object and read data from the object so we use from_object function from our config file.
So our settings.py will look like this.
def initialize_plugins(app):
# Initialize Plugins
db.init_app(app)
migrate.init_app(app, db)
So at this moment our settings.py will look like this.
from flask import Flask
import os
import config
from application import (
db,
migrate
)
def register_blueprints(app):
from application.controllers import (
home
)
app.register_blueprint(home.controller)
def initialize_plugins(app):
# Initialize Plugins
db.init_app(app)
migrate.init_app(app, db)
def import_models():
# import database models
from application.models import (
user
)
def initialize_flask_app():
# Initialize the core application.
app = Flask(
__name__,
instance_relative_config=False,
template_folder=config.Config.TEMPLATES_FOLDER,
static_folder=config.Config.STATIC_FOLDER,
static_url_path=config.Config.STATIC_FOLDER_PATH
)
app.config.from_object('config.Config')
return app
Now open init.py file and create create_app function at the end of the file.
def create_app():
from application.settings import (
initialize_flask_app,
initialize_plugins,
import_models,
register_blueprints
)
app = initialize_flask_app()
with app.app_context():
# initialize plugins
initialize_plugins(app)
# register blueprints
register_blueprints(app)
# import models
import_models()
return app
After this function our init.py will look like this.
from dotenv import load_dotenv
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import MetaData
load_dotenv()
convention = {
"ix": 'ix_%(column_0_label)s',
"uq": "uq_%(table_name)s_%(column_0_name)s",
"ck": "ck_%(table_name)s_%(column_0_name)s",
"fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
"pk": "pk_%(table_name)s"
}
metadata = MetaData(naming_convention=convention)
db = SQLAlchemy(metadata=metadata)
migrate = Migrate()
def create_app():
from application.settings import (
initialize_flask_app,
initialize_plugins,
import_models,
register_blueprints
)
app = initialize_flask_app()
with app.app_context():
# initialize plugins
initialize_plugins(app)
# register blueprints
register_blueprints(app)
# import models
import_models()
return app
firstly import all the functions from the settings.py file. initialize the flask app and set to the app variable.
Now we use app_context() to initialize all the functions which we imported from the settings.py and after that return the app obejct.
Now its time to add some code to our run.py to boot our applictaion.
from application import create_app
app = create_app()
if __name__ == '__main__':
app.run(host='0.0.0.0')
Simple import create_app function which we created in our init.py file and get call the function to get the flask object and with run method boot our application.
Now create a Database I cretaed the Database with the name of python_flask_blog.
and set your Database credentials in your .env file.
SQLALCHEMY_DATABASE_URI = "mysql+mysqlconnector://muhammadsaim:muhammadsaim@127.0.0.1:3306/python_flask_blog"
Now in your terminal initiate the flask migrate run this commad.
flask db init
This will create some migartion related configuration files in migartions folder which we created on the root folder.
Create a migration by running this command.
flask db migrate -m "Create User table."
This will create a file migartion version file to keep track of the changes so we can rollback to our migrations.
So we commit the migrations now run this command to push this commit to the Database this will cretae the users table.
flask db upgrade
And after that our table is created.
We have two tables 1st one is alembic_version and the other is users which we created but the first one is used by the migration to track the record of the migration.
Now finaly its time to run our Application for this we have to run this command.
python run.py
This command will open server and give us the url where our application will be served from our development server.
Open your browser and open this link on the broswer and we get the our index route which we cretaed in our home controller after opening this we have a page with written on this Home Controller
Hurray now we have our applictaion up.
You can get the updated code on GitHub Repo
Thanks for being with me.
See you guys in next post if you have any issue while going with this post feel free to comment.
Posted on August 22, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.