Flask Tutorial templates, webforms, database and user logins - Part 1
In this tutorial, you are going to learn how to set up a Flask project.
By the end of this chapter part 1 you are going to have a simple Flask web application login system
below is a list.
1. Templates
how to work with templates
2. Web Forms
how to work with web forms
To handle the web forms in this application we will use the Flask-WTF extension
install Flask-WTF in your virtual environment:
(venv) $ pip install flask-wtf
3. Database
how to work with databases.
To install Flask-SQLAlchemy in your virtual environment, make sure you have activated it first, and then run:
(venv) $ pip install flask-sqlalchemy
4. User Logins
how to create a user login subsystem
install Flask-Login in your virtual environment:
(venv) $ pip install flask-login
#app.py
from flask import Flask, render_template, flash, redirect, url_for
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, SubmitField
from wtforms.validators import DataRequired
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import LoginManager, UserMixin, current_user, login_user, logout_user, login_required
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///blog.db'
app.config['SECRET_KEY'] = 'cairocoders-ednalan'
login = LoginManager(app)
login.login_view = 'login'
db = SQLAlchemy(app)
class LoginForm(FlaskForm):
username = StringField('Username', validators=[DataRequired()])
password = PasswordField('Password', validators=[DataRequired()])
remember_me = BooleanField('Remember Me')
submit = SubmitField('Sign In')
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), index=True, unique=True)
email = db.Column(db.String(120), index=True, unique=True)
password_hash = db.Column(db.String(128))
def __repr__(self):
return ''.format(self.username)
def set_password(self, password):
self.password_hash = generate_password_hash(password)
def check_password(self, password):
return check_password_hash(self.password_hash, password)
class Post(db.Model):
id = db.Column(db.Integer, primary_key=True)
body = db.Column(db.String(140))
timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
def __repr__(self):
return ''.format(self.body)
@login.user_loader
def load_user(id):
return User.query.get(int(id))
@app.route('/')
@app.route('/index')
@login_required
def index():
user_post = {'username': 'cairocoders'}
hash = generate_password_hash('test1')
check_hash = check_password_hash(hash, 'test1')
posts = [
{
'author': {'username': 'tutorial1'},
'body': 'Beautiful day in Olongapo City!'
},
{
'author': {'username': 'turorial10'},
'body': 'Flask is a lightweight WSGI web application framework.!'
}
]
return render_template('index.html', title='Home', user_post=user_post, posts=posts, hash=hash, check_hash=check_hash)
@app.route('/login', methods=['GET', 'POST'])
def login():
if current_user.is_authenticated:
return redirect(url_for('index'))
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(username=form.username.data).first()
if user is None or not user.check_password(form.password.data):
flash('Invalid username or password')
return redirect(url_for('login'))
login_user(user, remember=form.remember_me.data)
return redirect(url_for('index'))
return render_template('login.html', title='Sign In', form=form)
@app.route('/logout')
def logout():
logout_user()
return redirect(url_for('index'))
if __name__ == '__main__':
app.run(debug=True)
//templates/index.html
{% extends "base.html" %}
{% block content %}
<p>hash, {{ hash }}!</p>
<p>Check hash, {{ check_hash }}</p>
<h1>Hi, {{ current_user.username }}!</h1>
{% for post in posts %}
<div><p>{{ post.author.username }} says: <b>{{ post.body }}</b></p></div>
{% endfor %}
{% endblock %}
//templates/base.html
<html>
<head>
{% if title %}
<title>{{ title }} - blog</title>
{% else %}
<title>Welcome to blog</title>
{% endif %}
</head>
<body>
<div>
Blog:
<a href="{{ url_for('index') }}">Home</a>
{% if current_user.is_anonymous %}
<a href="{{ url_for('login') }}">Login</a>
{% else %}
<a href="{{ url_for('logout') }}">Logout</a>
{% endif %}
</div>
<hr>
<p>Flask Tutorial templates, webforms, database and user logins - Part 1</p>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
{% block content %}{% endblock %}
</body>
</html>
//templates/login.html
{% extends "base.html" %}
{% block content %}
<h1>Sign In</h1>
<form action="" method="post" novalidate>
{{ form.hidden_tag() }}
<p>
{{ form.username.label }}<br>
{{ form.username(size=32) }}<br>
{% for error in form.username.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>
{{ form.password.label }}<br>
{{ form.password(size=32) }}<br>
{% for error in form.password.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>{{ form.remember_me() }} {{ form.remember_me.label }}</p>
<p>{{ form.submit() }}</p>
</form>
{% endblock %}
