Flask Jinja2, Forms & Auth

๐Ÿ Python 3.12+ ๐ŸŸข Chapter 49 of 65 ๐Ÿ“‚ Phase 10: Web Development ๐Ÿ“… 2026 Edition
๐Ÿ“Œ Covered in this chapter: Jinja2 Template Engine ยท Template Inheritance ({% extends %}) ยท Static Assets ยท Client Sessions (session) ยท Password Hashing (werkzeug.security) ยท Custom Error Pages (404)
Master server-side rendering and user authentication in Flask: the Jinja2 template engine, template inheritance with base layouts, managing user sessions with signed cryptographic cookies, hashing passwords with werkzeug.security, and handling 404/500 error pages.
1Server-Side Rendering with Jinja2 & Template Inheritance

Instead of hardcoding HTML strings inside Python functions, Flask uses the Jinja2 Template Engine. HTML templates are stored in a templates/ directory and rendered via render_template('page.html', var=value).

The 3 Core Jinja2 Delimiter Syntax Rules:

  • {{ expression }}: Prints the value of a Python variable or expression into the HTML (auto-escapes HTML tags to prevent XSS attacks).
  • {% statement %}: Controls program logic (e.g. {% if user %}, {% for item in items %}, {% extends 'base.html' %}).
  • {# comment #}: Server-side comments ignored during HTML rendering.

Template Inheritance Architecture (DRY Principle):

Instead of duplicating the HTML <head>, navbar, and footer across dozens of pages, you define a single base.html layout with {% block content %}{% endblock %} placeholders that child templates fill in!

๐Ÿ’ป Jinja2 Blueprint: Base Layout and Child Template Inheritance




  
  {% block title %}My Flask Portal{% endblock %}
  


  

  
{% block content %} {% endblock %}
{% extends "base.html" %} {% block title %}User Dashboard{% endblock %} {% block content %}

Welcome back, {{ username }}! ๐Ÿ‘‹

Your Enrolled Courses ({{ courses|length }}):

    {% for course in courses %}
  • {{ course.title }} - Instructor: {{ course.instructor }}
  • {% else %}
  • No courses enrolled yet.
  • {% endfor %}
{% endblock %}
๐Ÿ” Template Filters:

Jinja2 includes powerful pipe filters like {{ username|upper }} (capitalizes string), {{ courses|length }} (counts items), and {{ post.date|format_date }}.

2User Sessions & Secure Password Hashing with werkzeug.security

HTTP is a stateless protocol. To remember that a user has successfully logged in across multiple page clicks, Flask provides the session dictionary.

How Flask Sessions Work:

Flask serializes the session dictionary into a Cryptographically Signed Cookie stored in the user's browser. The user can view the cookie, but cannot tamper with or modify its values without invalidating the cryptographic signature (calculated using app.secret_key).

Security Rule: NEVER Store Plaintext Passwords!

Always hash user passwords using one-way cryptographic hash functions (like PBKDF2 with SHA-256 and salted hashes) via werkzeug.security:

๐Ÿ’ป Example 2: Complete User Authentication Flow with Password Hashing & Sessions
from flask import Flask, render_template_string, request, session, redirect, url_for
from werkzeug.security import generate_password_hash, check_password_hash

app = Flask(__name__)
# Cryptographic secret key used to sign session cookies:
app.secret_key = "super_secret_production_key_change_in_env"

# Simulated User Database with Hashed Passwords:
USERS_DB = {
    "balaji": generate_password_hash("SuperSecret2026!") # Stored as salted hash!
}

@app.route("/login", methods=["GET", "POST"])
def login():
    if request.method == "POST":
        username = request.form.get("username")
        password = request.form.get("password")

        # 1. Verify user exists and check password hash:
        stored_hash = USERS_DB.get(username)
        if stored_hash and check_password_hash(stored_hash, password):
            # 2. Store user in session cookie:
            session["user"] = username
            return redirect(url_for("profile"))
        
        return "

โŒ Invalid Username or Password

Try again", 401 # Render simple login form: return '''

๐Ÿ” User Login





''' @app.route("/profile") def profile(): # 3. Check if user session exists: if "user" not in session: return redirect(url_for("login")) return f"

๐ŸŽ‰ Welcome to your private profile, {session['user']}!

Log Out" @app.route("/logout") def logout(): session.pop("user", None) # Clear session return redirect(url_for("login")) # Custom 404 Error Handler: @app.errorhandler(404) def page_not_found(error): return "

404 - Oops! The requested page does not exist.

Go Home", 404
๐Ÿ” Security Breakdown:
  • generate_password_hash("pass") creates a random salt and hashes it (e.g. pbkdf2:sha256:600000$...). Even if two users have the same password, their hashes are completely different.
  • check_password_hash(hash, pass) safely compares the input password against the salt in constant time to prevent timing attacks.
โš ๏ธ Common Developer Pitfall: Storing Sensitive Confidential Data (like Credit Card numbers) in Flask Sessions

By default, Flask sessions are client-side signed cookies. While the user cannot tamper with the cookie, the payload is NOT encrypted and can be easily decoded by anyone inspecting browser cookies! Only store non-sensitive identifiers like user_id in the session.

๐Ÿ’ป Hands-on Interactive Practice Challenge

Create a password validator helper that generates a hash for a new user and validates whether a submitted login password matches.

Python 3 Practice Challenge โ–ถ Run in Compiler
from werkzeug.security import generate_password_hash, check_password_hash

raw_pass = "PythonRocks2026"
hashed_pass = generate_password_hash(raw_pass)

print("Generated Salted Hash:", hashed_pass)
print("Correct Password Match:  ", check_password_hash(hashed_pass, "PythonRocks2026")) # True
print("Incorrect Password Match:", check_password_hash(hashed_pass, "WrongPassword"))    # False
Run This Challenge in Online Python IDE โ†’
โ“ Frequently Asked Questions (FAQ)

Q What is CSRF (Cross-Site Request Forgery) in web forms?

CSRF is an exploit where a malicious website tricks a user's browser into performing an unauthorized action on a site where they are logged in. Prevent it using Flask-WTF CSRF tokens in all POST forms.

Q What is the difference between client-side sessions and server-side sessions?

Flask's default session stores signed data in browser cookies. Server-side session extensions (like Flask-Session) store session data in Redis or a database, sending only an opaque session UUID to the browser cookie.

Q How do custom error handlers work in Flask?

Decorating a function with @app.errorhandler(404) or @app.errorhandler(500) intercepts HTTP error codes across the entire application and returns a custom-styled error template.

OC
Written by Our Compiler Technical Editorial Team
Reviewed for accuracy & tested on Python 3.12+ runtime ยท Last updated August 2026