Flask is a web framework for Python. It facilitates the creation of web apps (dynamic web pages).
Run Flask
Flask comes with its own server for debugging purposes, which can be started with:
flask run
Folder Structure
app.py # main code
requirements.txt # required libraries
static/ # files that never change
templates/ # dynamic files
“Hello, name” — Example App
templates/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta name = "viewport" content="initial-scale=1, width=device-width">
<title>Hello</title>
</head>
<body>
hello, {{ name_placeholder }} <!-- Jinja template -->
</body>
</html>
app.pyhttp://website.domain/?name=Trude
from flask import Flask, render_template, request
app = Flask(__name__)
# When user visits / (the website root), load index.html.
# If the key name exists, store the value in a variable. If not, store world.
@app.route("/")
def index():
name = request.args.get("name", "world")
return render_template("index.html", name_placeholder=name)
HTML Form
Sample App
templates/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta name = "viewport" content="initial-scale=1, width=device-width">
<title>Hello</title>
</head>
<body>
<form>
<input autocomplete="off" autofocus name="name" placeholder="Name" type="text">
<button type="submit">Greet</button>
</form>
</body>
</html>
app.pyhttp://website.domain/?name=Trude
from flask import Flask, render_template, request
app = Flask(__name__)
# When user visits / (the website root), load index.html.
# If the key name exists, store the value in a variable. If not, store world.
@app.route("/")
def index():
name = request.args.get("name", "world")
return render_template("index.html", name_placeholder=name)
Custom Route
Both the form and /greet works.
templates/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta name = "viewport" content="initial-scale=1, width=device-width">
<title>Hello</title>
</head>
<body>
<form action="/greet" method="get">
<input autocomplete="off" autofocus name="name" placeholder="Name" type="text">
<button type="submit">Greet</button>
</form>
</body>
</html>
templates/greet.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta name = "viewport" content="initial-scale=1, width=device-width">
<title>Hello</title>
</head>
<body>
hello,{{name}}
</body>
</html>
app.pyhttp://website.domain/?name=Trude
from flask import Flask, render_template, request
app = Flask(__name__)
# When user visits / (the website root), load index.html.
# If the key name exists, store the value in a variable. If not, store world.
@app.route("/")
def index():
name = request.args.get("name", "world")
return render_template("index.html", name_placeholder=name)
@app.route("/greet")
def greet():
return render_template("greet.html", name=request.args.get("name", "world"))
Avoid HTML Repetition
Use a layout instead of copying blocks.
templates/index.html
{% extends "layout.html" %}
{% block body %}
<form action="/greet" method="get">
<input autocomplete="off" autofocus name="name" placeholder="Name" type="text">
<button type="submit">Greet</button>
</form>
{% endblock %}
templates/greet.html
{% extends "layout.html" %}
{% block body %}
hello, {{name}}
{% endblock %}
templates/layout.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta name = "viewport" content="initial-scale=1, width=device-width">
<title>Hello</title>
</head>
<body>
{% block body %}{% endblock %}
</body>
</html>
app.pyhttp://website.domain/?name=Trude
from flask import Flask, render_template, request
app = Flask(__name__)
# When user visits / (the website root), load index.html.
# If the key name exists, store the value in a variable. If not, store world.
@app.route("/")
def index():
name = request.args.get("name", "world")
return render_template("index.html", name_placeholder=name)
@app.route("/greet")
def greet():
return render_template("greet.html", name=request.args.get("name", "world"))
Hide Sensitive Requests from the URL
Use post instead of get.
templates/index.html
{% extends "layout.html" %}
{% block body %}
<form action="/greet" method="post">
<input autocomplete="off" autofocus name="name" placeholder="Name" type="text">
<button type="submit">Greet</button>
</form>
{% endblock %}
templates/greet.html
{% extends "layout.html" %}
{% block body %}
hello, {{name}}
{% endblock %}
templates/layout.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta name = "viewport" content="initial-scale=1, width=device-width">
<title>Hello</title>
</head>
<body>
{% block body %}{% endblock %}
</body>
</html>
app.pyhttp://website.domain/greet
The name doesn’t appear in the URL anymore.
from flask import Flask, render_template, request
app = Flask(__name__)
# When user visits / (the website root), load index.html.
# If the key name exists, store the value in a variable. If not, store world.
@app.route("/")
def index():
name = request.args.get("name", "world")
return render_template("index.html", name_placeholder=name)
@app.route("/greet", methods=["POST"])
def greet():
return render_template("greet.html", name=request.form.get("name", "world"))
Combine Routes to save Resources
GET is always the default.
POST is used to send information to the server.
templates/index.html
{% extends "layout.html" %}
{% block body %}
<form action="/" method="post">
<input autocomplete="off" autofocus name="name" placeholder="Name" type="text">
<button type="submit">Greet</button>
</form>
{% endblock %}
templates/greet.html
{% extends "layout.html" %}
{% block body %}
hello, {{name}}
{% endblock %}
templates/layout.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta name = "viewport" content="initial-scale=1, width=device-width">
<title>Hello</title>
</head>
<body>
{% block body %}{% endblock %}
</body>
</html>
app.pyhttp://website.domain/
from flask import Flask, render_template, request
app = Flask(__name__)
# When user visits / (the website root), load index.html.
# If the key name exists, store the value in a variable. If not, store world.
@app.route("/", methods=["GET, POST"])
def index():
if request.method == "GET":
return render_template("index.html")
elif request.method == "POST":
return render_template("greet.html", name=request.form.get("name", "world"))
Cookies - Session
Used to store data and to recognize the user.
- Server → Client
Set-Cookie session=value
- Client → Server
Cookie session
from flask import session
# Configure app
app = Flask(__name__)
# Configure session
app.config["SESSION_PERMANENT"] = False
app.config["SESSION_TYPE"] = "filesystem"
Session(app)
# Redirect to login if no cookie exists
@app.route("/")
def index():
if not session.get("name"):
return redirect("/login")
return render_template("index.html")
# EXAMPLES
# session is a dictionary
session["cart"] = []
books = db.execute("SELECT * FROM books WHERE id IN (?)", session["cart"])