In this Flask tutorial we are going to learn about Flask Login & Flask Logout Tutorial , so for
this we are using a Flask Extension that is called Flask-Login. Flask-Login provides user
session management for Flask. It handles the common tasks of logging in, logging out,
and remembering your users’ sessions over extended periods of time. you can check
Flask-Login documentation for more.
Installation
Install the extension with pip:
1 |
pip install flask-login |
The most important part of an application that uses Flask-Login is the LoginManager
class. You should create one for your application somewhere in your code, for example
we are using the LoginManager in our app.py file.
1 |
login_manager = LoginManager() |
Also you need to provide a user_loader
callback. This callback is used to
reload the user object from the user ID stored in the session.
So now let’s add the complete code for app.py.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
from flask import Flask, render_template, flash, request, redirect, url_for from forms import LoginForm, RegistrationForm from flask_sqlalchemy import SQLAlchemy from werkzeug.security import check_password_hash, generate_password_hash from flask_login import LoginManager, UserMixin from flask_login import login_user, logout_user, current_user, login_required #create the object of Flask app = Flask(__name__) app.config['SECRET_KEY'] = 'hardsecretkey' #SqlAlchemy Database Configuration With Mysql app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:''@localhost/flaskcodeloop' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False db = SQLAlchemy(app) #login code login_manager = LoginManager() login_manager.init_app(app) login_manager.login_view = 'Login' #This is our model class UserInfo(UserMixin, db.Model): id = db.Column(db.Integer, primary_key = True) username = db.Column(db.String(100), unique = True) password = db.Column(db.String(100)) def __init__(self, username, password): self.username = username self.password = password @login_manager.user_loader def load_user(user_id): return UserInfo.query.get(int(user_id)) #creating our routes @app.route('/') @login_required def index(): name = current_user.username return render_template('index.html', name = name) #login route @app.route('/login' , methods = ['GET', 'POST']) def Login(): form = LoginForm() if request.method == 'POST': if form.validate_on_submit(): user = UserInfo.query.filter_by(username=form.username.data).first() if user: if check_password_hash(user.password, form.password.data): login_user(user) return redirect(url_for('index')) flash("Invalid Credentials") return render_template('login.html', form = form) @app.route('/logout') @login_required def logout(): logout_user() return redirect(url_for('Login')) #register route @app.route('/register' , methods = ['GET', 'POST']) def register(): form = RegistrationForm() if form.validate_on_submit(): hashed_password = generate_password_hash(form.password.data, method = 'sha256') username = form.username.data password = hashed_password new_register =UserInfo(username=username, password=password) db.session.add(new_register) db.session.commit() flash("Registration was successfull, please login") return redirect(url_for('Login')) return render_template('registration.html', form=form) #run flask app if __name__ == "__main__": app.run(debug=True) |
OK in the app.y file , these are the imports that we need for Flask Login & Flask Logout Tutorial.
1 2 |
from flask_login import LoginManager, UserMixin from flask_login import login_user, logout_user, current_user, login_required |
This is Flask SQLAlchemy configuration for mysql database, we have already covered this
article, you can check this link Flask SQLAlchemy with Mysql . make sure that you have
created a database in the Wamp Server, my database name is flaskcodeloop .
1 2 |
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:''@localhost/flaskcodeloop' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False |
Also we need to create LoginManager object, and initialize our LoginManager.
1 2 3 |
login_manager = LoginManager() login_manager.init_app(app) login_manager.login_view = 'Login' |
This is our database model that we have already covered in Flask WTF Forms .
1 2 3 4 5 6 7 8 9 10 |
class UserInfo(UserMixin, db.Model): id = db.Column(db.Integer, primary_key = True) username = db.Column(db.String(100), unique = True) password = db.Column(db.String(100)) def __init__(self, username, password): self.username = username self.password = password |
As i have said that you need to provide a user_loader
callback. This
callback is used to reload the user object from the user ID stored in the session.
1 2 3 |
@login_manager.user_loader def load_user(user_id): return UserInfo.query.get(int(user_id)) |
Also in our index route we have used login_required decorator, now no one can access
our index page without login. and in here you can see we are getting the current logged
in username. we render this username in our index.html.
1 2 3 4 5 6 7 |
@app.route('/') @login_required def index(): name = current_user.username return render_template('index.html', name = name) |
This is our login route, in this route we are checking the user against our database registered
users, if the credentials were valid, we login the user and redirect the user to the index page,
if user credentials were not valid we are giving a flash message.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
@app.route('/login' , methods = ['GET', 'POST']) def Login(): form = LoginForm() if request.method == 'POST': if form.validate_on_submit(): user = UserInfo.query.filter_by(username=form.username.data).first() if user: if check_password_hash(user.password, form.password.data): login_user(user) return redirect(url_for('index')) flash("Invalid Credentials") return render_template('login.html', form = form) |
And this is our logout view.
1 2 3 4 5 |
@app.route('/logout') @login_required def logout(): logout_user() return redirect(url_for('Login')) |
Our forms.py file, we have just our LoginForm and RegistrationForm.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
from flask_wtf import FlaskForm from wtforms import StringField, PasswordField from wtforms.validators import InputRequired class LoginForm(FlaskForm): username = StringField('Username', validators=[InputRequired()]) password = PasswordField('Password', validators=[InputRequired()]) class RegistrationForm(FlaskForm): username = StringField('Username', validators=[InputRequired()]) password = PasswordField('Password', validators=[InputRequired()]) |
Note : You need to use this command for creating your model table in the database.
1 2 |
>>> from app import db >>> db.create_all() |
Our base.html file, also we have added our login and signup buttons with logout link.
templates/base.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>{% block title %} {% endblock %}</title> <!-- CSS Bootstrap CDN Link --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous"> </head> <body> <nav class="navbar navbar-expand-lg navbar-dark bg-dark"> <div class="container"> <a class="navbar-brand" href="{{url_for('index')}}">CodeLoop</a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <ul class="navbar-nav mr-auto"> <li class="nav-item active"> <a class="nav-link" href="{{url_for('index')}}">Home <span class="sr-only">(current)</span></a> </li> <li class="nav-item"> <a class="nav-link" href="{{url_for('logout')}}">Logout</a> </li> </ul> <form class="form-inline my-2 my-lg-0"> <input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search"> <button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button> </form> </div> </div> <a href="{{url_for('Login')}}"><button class="btn btn-success navbar-btn">Login</button> </a> <a href="{{url_for('register')}}"><button class="btn btn-success navbar-btn">Signup</button> </a> </nav> <!-- JS, Popper.js, and jQuery --> <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script> {% block body %} {% endblock %} </body> </html> |
This is our registration.html, and we have simply rendered our form with our Flash Message.
templates/registration.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
{% extends 'base.html' %} {% block title %} Home {% endblock %} {% block body %} <div class="container"> <h1>Registration Page - Welcome to codeloop.org</h1> <h3>Tutorial Number 13 </h3> <br> <br> <hr> {% with messages = get_flashed_messages() %} {% if messages %} {% for message in messages %} <div class="alert alert-success alert-dismissable" role="alert"> <button type="button" class="close" data-dismiss="alert" aria-label="close"> <span aria-hidden="true">X</span> </button> {{message}} </div> {% endfor %} {% endif %} {% endwith %} <h1>Please Register</h1> <form action="" method="post" novalidate> {{form.csrf_token}} <p> {{form.username.label}} {{form.username(size=32)}} {% for error in form.username.errors %} <span style="color:red;"> {{error}} </span> {% endfor %} </p> <p> {{form.password.label}} {{form.password(size=32)}} {% for error in form.password.errors %} <span style="color:red;"> {{error}} </span> {% endfor %} </p> <p> <input type="submit" value="Register" class="btn btn-success"> </p> </form> </div> {% endblock %} |
In here we have login.html file.
templates/login.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
{% extends 'base.html' %} {% block title %} Home {% endblock %} {% block body %} <div class="container"> <h1>Home Page - Welcome to codeloop.org</h1> <h3>Tutorial Number 13 </h3> <br> <br> <hr> {% with messages = get_flashed_messages() %} {% if messages %} {% for message in messages %} <div class="alert alert-success alert-dismissable" role="alert"> <button type="button" class="close" data-dismiss="alert" aria-label="close"> <span aria-hidden="true">X</span> </button> {{message}} </div> {% endfor %} {% endif %} {% endwith %} <h1>Please Login</h1> <form action="" method="post" novalidate> {{form.csrf_token}} <p> {{form.username.label}} {{form.username(size=32)}} {% for error in form.username.errors %} <span style="color:red;"> {{error}} </span> {% endfor %} </p> <p> {{form.password.label}} {{form.password(size=32)}} {% for error in form.password.errors %} <span style="color:red;"> {{error}} </span> {% endfor %} </p> <p> <input type="submit" value="Login" class="btn btn-success"> </p> </form> </div> {% endblock %} |
This is our index.html.
templates/index.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
{% extends 'base.html' %} {% block title %} Home {% endblock %} {% block body %} <div class="container"> <h1>Home Page - Welcome to codeloop.org</h1> <h3>Tutorial Number 13 </h3> <p> In this tutorial we are going to talk about Flask Login and Logout. </p> <h2>Hello Mr. {{name}}</h2> </div> {% endblock %} |
Now run your Flask Project and go to http://localhost:5000/, you can see that
we can not access to index page and it is redirecting us to the login page.
If you give your valid credentials, you will be redirected to the index page.
Also you can watch my complete 4 hours training on Flask Web Development.
Subscribe and Get Free Video Courses & Articles in your Email
Comments are closed.