Flask uses the MVC (Model View Controller) Framework. Just to make this as obvious as possible, I like my Flask apps to have the following.
- Model -> models.py
- View -> views.py
- Controller -> __init__.py
Let's say your Flask app has the following files.
├── main.py
├── database (directory)
│ ├── example.db
├── my-project (directory)
│ ├── __init__.py
│ ├── views.py
│ ├── models.py
│ ├── templates (directory)
│ │ ├── base.html
│ │ ├── home.html
│ │ ├── results.html
│ └── static (directory)
│ └── custom.css
Flask-Login can be used to create session objects after a user has been authenticated. First, use pip to install Flask-Login.
pip install Flask-Login
This assumes you already have some sort of sign in form that is used to check if a users username and password are valid.
In your controller (__init__.py in this example), setup the Login Manager.
- In this example, from .models import users is used to import the users table from the model (models.py in this example)
- login_manager.login_view = 'views.SignIn' to use the /SignIn route in the view (views.py in this example)
import sqlite3
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
db = SQLAlchemy()
def app_obj():
app = Flask(__name__)
app.config['SECRET_KEY'] = 'some_unique_string_of_data'
# VIEWS
from .views import views
app.register_blueprint(views, url_prefix='/')
# database
uri = "sqlite:///example.db"
app.config['SQLALCHEMY_DATABASE_URI'] = uri
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db.init_app(app)
# LOGIN MANAGER
from .models import users
login_manager = LoginManager()
login_manager.login_view = 'views.SignIn'
login_manager.init_app(app)
@login_manager.user_loader
def load_user(id):
return users.query.get(int(id))
return app
In your model (models.py in this example), let's say you have a table named users. UserMixin is needed to be able to use current_user in your view.
from sqlalchemy import func
from flask_login import UserMixin
from . import db
class users(db.Model, UserMixin):
id = db.Column(db.Integer, nullable=False, unique=True, primary_key=True)
email = db.Column(db.String(50), nullable=False, unique=False)
password = db.Column(db.String(100), nullable=False, unique=False)
Your view could have something like this.
from flask import flash, redirect, url_for
from flask_login import login_user, current_user
from . import db
@views.route('/SignIn', methods=['GET', 'POST'])
def signin():
from .models import users
data = users.query.filter_by(email=request.form.get('email')).first()
print(f"data = {data}")
if data == None:
print(f"no user found with {email}")
else:
print(f"current_user.is_authenticated before login_user = {current_user.is_authenticated}")
print(f"current_user.is_active before login_user = {current_user.is_active}")
login_user(data)
print(f"current_user.is_authenticated after login_user = {current_user.is_authenticated}")
print(f"current_user.is_active after login_user = {current_user.is_active}")
flash('Successfully Signed In' ,category='primary')
return redirect(url_for('views.home'))
Should return the following. In this example, since the "data" variable has <users 123>, this means there is a result was found in the "users" table with ID 123. Or you could add def is_active(self) return True in your model.
data = <users 123>
current_user.is_authenticated before login_user = False
current_user.is_active before login_user = False
current_user.is_authenticated after login_user = True
current_user.is_active after login_user = True
Or perhaps like this.
- In this example, from .models import users is used to import the users table from the model (models.py in this example)
- users.query.filter_by(email=request.form.get('email')).first() is used to see if the users email exists in the users table
- check out my article on check_password_hash
- login_user is used to create session objects
- logout_user is used to destroy the session objects
from flask import flash, redirect, url_for
from flask_login import login_user, login_required, logout_user, current_user
from . import db
from werkzeug.security import check_password_hash
@views.route('/SignIn', methods=['GET', 'POST'])
def signin():
from .models import users
data = users.query.filter_by(email=request.form.get('email')).first()
password_hash = check_password_hash(data.password, request.form.get('password'))
login_user(data)
flash('Successfully Signed In' ,category='primary')
return redirect(url_for('views.home'))
@views.route('/SignOut')
@login_required <- only allow access to this route if user is logged in
def signout():
logout_user()
flash('Successfully Signed Out' ,category='primary')
return redirect(url_for('views.home'))
If login_user is successful, 2 cookies should be created in the users web browser, remember_token and session.
On your HTML pages, you should then be able to use current_user to do whatever it is that you want to do when a user has been authenticated.
{% current_user.is_authenticated and current_user.is_active %}
current_user.is_authenticated = {{ current_user.is_authenticated }}<br />
current_user.is_active = {{ current_user.is_active }}<br />
current_user.is_anonymous = {{ current_user.is_anonymous }}<br />
current_user.get_id = {{ current_user.get_id }}<br />
{% endif %}
Did you find this article helpful?
If so, consider buying me a coffee over at