python flask web HTTP jinja2 framework

Flask: building web apps with Python

Learning objectives

By the end of this guide you will be able to:

  • understand how a web app works and the role of Flask;
  • create a local server with routes and associated functions;
  • handle GET and POST requests;
  • use HTML templates with Jinja2;
  • manage forms, cookies and sessions;
  • correctly structure a mini Flask application.

What is Flask

Flask is a micro web framework for Python: lightweight, flexible and ideal for learning how web applications work. It imposes no rigid structure and lets you add only what you need.

Note: Flask is built on two main components:

  • Werkzeug – handles HTTP requests and responses;
  • Jinja2 – a template engine for generating dynamic HTML pages.

Installation and first example

Install Flask with:

pip install flask

Create a file app.py:

from flask import Flask

app = Flask(__name__)

@app.route("/")
def home():
    return "Hello from the Flask server!"

if __name__ == "__main__":
    app.run(debug=True)

Run with: python app.py → open your browser at http://127.0.0.1:5000

Routes and HTTP methods

Every route is a Python function associated with a URL.

@app.route("/info")
def info():
    return "<h2>Server information</h2>"

@app.route("/greet/<name>")
def greet(name):
    return f"Hello, {name}!"

You can specify HTTP methods:

@app.route("/data", methods=["GET", "POST"])
def data():
    if request.method == "POST":
        return "You submitted data!"
    else:
        return "Data query page"

HTML templates with Jinja2

Create a templates/ folder and add an index.html file:

<!DOCTYPE html>
<html lang="en">
  <head><meta charset="UTF-8"><title>Welcome</title></head>
  <body>
    <h1>Hello, {{ name }}</h1>
  </body>
</html>

In the Python file:

from flask import render_template

@app.route("/page/<name>")
def page(name):
    return render_template("index.html", name=name)

Forms and POST requests

from flask import request

@app.route("/login", methods=["GET", "POST"])
def login():
    if request.method == "POST":
        user = request.form["user"]
        return f"Welcome, {user}!"
    return '''
        <form method="POST">
            Username: <input name="user">
            <input type="submit" value="Login">
        </form>
    '''

Redirects and flash messages

You can redirect the user and display temporary messages:

from flask import redirect, url_for, flash

app.secret_key = "secret_key"

@app.route("/start")
def start():
    flash("Login successful!")
    return redirect(url_for("home"))

In the template:

{% with messages = get_flashed_messages() %}
  {% for msg in messages %}
    <p style="color:green">{{ msg }}</p>
  {% endfor %}
{% endwith %}

Static files and project structure

Flask automatically looks for static files in the static/ folder (e.g. images, CSS, JavaScript).

project/
 |-- app.py
 |-- templates/
 |   |-- index.html
 |-- static/
      |-- style.css

Sessions and Cookies

Sessions allow you to store information server-side across multiple requests.

from flask import session

app.secret_key = "supersecret"

@app.route("/set/<user>")
def set_user(user):
    session["user"] = user
    return f"Session set for {user}"

@app.route("/who")
def who():
    if "user" in session:
        return f"Active user: {session['user']}"
    return "No active session"

Final mini-project: login and greeting

from flask import Flask, render_template, request, redirect, url_for, session

app = Flask(__name__)
app.secret_key = "flaskpillolona"

@app.route("/", methods=["GET", "POST"])
def login():
    if request.method == "POST":
        name = request.form["name"]
        session["user"] = name
        return redirect(url_for("home"))
    return render_template("login.html")

@app.route("/home")
def home():
    if "user" not in session:
        return redirect(url_for("login"))
    return render_template("home.html", name=session["user"])

@app.route("/logout")
def logout():
    session.pop("user", None)
    return redirect(url_for("login"))

login.html:

<form method="POST">
  <input name="name" placeholder="Username">
  <button type="submit">Login</button>
</form>

home.html:

<h2>Hello {{ name }}!</h2>
<a href="{{ url_for('logout') }}">Logout</a>

POST requests with JSON data and Query Parameters

Besides HTML forms, Flask can receive and send data as JSON or via URL parameters.

Receiving JSON data

When a client sends a request with Content-Type: application/json, Flask lets you read the body via request.get_json().

from flask import jsonify

@app.route("/api/data", methods=["POST"])
def receive_json():
    data = request.get_json()
    name = data.get("name")
    grade = data.get("grade")
    return jsonify({
        "message": f"Data received for {name}",
        "average": (grade + 10) / 2
    })

Note: You can test this from the terminal with:

curl -X POST -H "Content-Type: application/json" \
-d '{"name": "Luca", "grade": 8}' \
http://127.0.0.1:5000/api/data

Query string parameters

Parameters in the URL query string (e.g. ?user=Mario&score=90) are read via request.args.

@app.route("/score")
def score():
    user   = request.args.get("user", "Anonymous")
    points = request.args.get("score", 0, type=int)
    return f"{user} scored {points} points!"

Note: Example: http://127.0.0.1:5000/score?user=Luca&score=95

Cookies allow you to store small pieces of information in the user’s browser.

from flask import make_response

@app.route("/set_cookie")
def set_cookie():
    resp = make_response("Cookie set!")
    resp.set_cookie("user", "Julia", max_age=60*60*24)  # valid 1 day
    return resp
@app.route("/get_cookie")
def get_cookie():
    user = request.cookies.get("user")
    if user:
        return f"Welcome back, {user}!"
    return "No cookie found."
@app.route("/del_cookie")
def del_cookie():
    resp = make_response("Cookie deleted.")
    resp.delete_cookie("user")
    return resp

Note: Cookies are managed by the browser and sent automatically with every request to the same domain, making it possible to maintain sessions or user preferences.


In brief: Flask is a powerful and accessible tool for building dynamic web apps with Python. With just a few files you can create APIs, dashboards and complete applications, integrating HTML, CSS and databases.