Flask Blueprint, Flask-Login, SQLAlchemy

Nick Rodriguez
3 min readSep 3, 2022

No flask-sqlalchemy

Homepage for the application in this article

This article goes over the key steps to build a Flask application with Flask Blueprint, Flask-Login and SQLAlchemy.

Github repositories for this article:

webApp02

webApp02-packages

In this article I just go over the __init__.py and the routes to register and login users because those are a little different than what is conventionally done in a flask app when you use flask-sqlalchemy.

Flask Blueprint framework

Folder structure

C:\Users\Costa Rica\Documents\webApp02\
| .gitignore
| run.py
|
\---app_package
| __init__.py
|
+---templates
| home.html
| login.html
| page.html
| protected_page.html
|
\---users
| routes.py
\---__init__.py

nr_config and nr_models

nr_config and nr_models are custom modules that I built and installed into the pip/venv environment. It is not hard once you know how to do it. I go into details about how I do that in this article.

__init__.py

from flask import Flask
from nr_config import ConfigDev
from nr_models import login_manager
config_object = ConfigDev()def create_app():
app = Flask(__name__)
app.config.from_object(config_object)
login_manager.init_app(app)
from app_package.users.routes import users
app.register_blueprint(users)
return app

The two main things here are:

1. Import the ConfigDev class access your external json file with all your configuration and sensitive information you don’t want to store in the application files. Flask needs this as seen in the “app.config.from_object(config_object)” line above. If you want to take a closer look at what is in the ConfigDev class see the Github repo webApp02-packages.

2. Import login_manager object and init in create_app() method to make the connection between the models.py file (Users model and user_loader decorator).

Imports(routes.py)

The routes.py file has more parts to be aware of first let’s look at the imports:

from flask import Blueprint
from flask import render_template, url_for, redirect, flash, request, abort, session,\
Response, current_app, send_from_directory
import bcrypt
from nr_models import sess, Users
from flask_login import login_required, login_user, logout_user, current_user

Differences form conventional flask tutorials using

1. Import bcrypt instead of bcrypt from what I usually call the “app_package” in all my flask applications. The app_package is everything the __init__.py file that contains the create_app() method in the first subfolder of your package. Typically, in the __init__.py file you’ll import flask-bcrypt and make a bcrypt object that gets passed through the application. But in this case we’ll just use the bcrypt library, generate a salt object, and from then on the bcrypt operations will look similar with some differences in the syntax.

2. Import the sess object from nr_models, i.e. the custom package I made and referenced in the first section of this article. This object is analogous to what we typically call the “db” object in most conventional flask tutorials using flaks-sqlalchemy. For the most part it does a lot of the same things but not all and some of the syntax (i.e. writing queries) are a little different.

Register User(routes.py)

Create a salt to initiate the hash for encrypting the password in the register route. This is how users will add their password to the database. The bcrypt.haspw() method is used. It has two arguments the password the new user wishes to register (encoded) and the salt.

salt = bcrypt.gensalt()@users.route(‘/register’, methods = [‘GET’, ‘POST’])
def register():
page_name = ‘Register’
if request.method == ‘POST’:
formDict = request.form.to_dict()
hash_pw = bcrypt.hashpw(formDict.get(‘password’).encode(), salt)
new_user = Users(email = formDict.get(‘email’), password = hash_pw)
sess.add(new_user)
sess.commit()
return redirect(url_for(‘users.login’))
return render_template(‘login.html’, page_name = page_name)

Also, you can see in the register route how the sess object is used to add and commit a new user — much like db.

Login (routes.py)

Once a user is registered and wants to login you’ll use bcrypt.checkpw() to verify the password. This accepts two arguments the password passed though the login and then the second is the stored encrypted password in the database. You’ll notice I have to encode the password used to login.

@users.route(‘/login’, methods = [‘GET’, ‘POST’])
def login():
print(‘* in login *’)
page_name = ‘Login’
if request.method == ‘POST’:
formDict = request.form.to_dict()
email = formDict.get(‘email’)
user = sess.query(Users).filter_by(email=email).first()
# verify password using hash
if formDict.get(‘password’):
if bcrypt.checkpw(formDict.get(‘password’).encode(), user.password):
print(“match”)
login_user(user)
flash(‘Logged in succesfully’)
return redirect(url_for(‘users.login’))
else:
print(“does not match”)

Why not just use Flask-Sqlalchemy?

The reason for not using flask-sqlalchemy is to share the models.py file with other applications. I think there are a few ways of doing this but using SQLAlchemy instead of flask-sqlalchemy in the models.py file has worked well.

--

--