Kahibaro
Discord Login Register

Routing and templates

Understanding Routing in Flask

In web development with Flask, routing decides which Python code runs when someone visits a specific URL (like /, /about, /hello/jane, etc.).

In the Flask introduction, you saw a very simple route. Here, we will:

Everything below assumes you already have a basic Flask app set up.

Defining Routes with `@app.route()`

Flask uses a decorator, @app.route(), to connect URLs to Python functions.

Basic example with two routes:

from flask import Flask
app = Flask(__name__)
@app.route("/")
def home():
    return "Welcome to the homepage!"
@app.route("/about")
def about():
    return "This is the about page."
if __name__ == "__main__":
    app.run(debug=True)

Each route:

Dynamic Routes: Variables in the URL

Sometimes you want part of the URL to be dynamic, like:

You can capture part of the URL as a variable:

from flask import Flask
app = Flask(__name__)
@app.route("/hello/<name>")
def hello(name):
    return f"Hello, {name}!"
if __name__ == "__main__":
    app.run(debug=True)

Now:

Here name comes from the URL and is passed to the hello function as an argument.

Type-Constrained Variables in Routes

By default, dynamic parts are strings. You can also specify types:

Example:

from flask import Flask
app = Flask(__name__)
@app.route("/post/<int:post_id>")
def show_post(post_id):
    # post_id is an integer here
    return f"This is post number {post_id}"
if __name__ == "__main__":
    app.run(debug=True)

Now:

Another example with path:

@app.route("/files/<path:filename>")
def show_file(filename):
    return f"You requested the file: {filename}"

Named Routes with `url_for()`

Instead of hard-coding URLs as strings, Flask lets you build URLs from the function name using url_for.

This is useful when:

Example:

from flask import Flask, url_for
app = Flask(__name__)
@app.route("/")
def index():
    home_url = url_for("index")
    about_url = url_for("about")
    return f"Home URL: {home_url}, About URL: {about_url}"
@app.route("/about")
def about():
    return "About page"
if __name__ == "__main__":
    app.run(debug=True)

url_for("index") will return / and url_for("about") will return /about.

You’ll see url_for used a lot inside templates next.

Introduction to Templates

So far, we returned simple text from routes. In real web apps, we usually send HTML pages. Flask uses templates (HTML with placeholders) to do that.

Templates let you:

Flask uses a template engine called Jinja2, but you don’t need to remember the name now—just the idea: HTML + special syntax for dynamic parts.

Setting Up a `templates` Folder

Flask looks for templates in a folder called templates by default.

Typical structure:

your_project/
    app.py
    templates/
        index.html
        about.html

Rendering Templates with `render_template()`

To return an HTML template from a route, use render_template.

Example:

from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def home():
    return render_template("index.html")
@app.route("/about")
def about():
    return render_template("about.html")
if __name__ == "__main__":
    app.run(debug=True)

index.html and about.html must be in the templates folder.

Example index.html:

<!DOCTYPE html>
<html>
<head>
    <title>My First Flask Page</title>
</head>
<body>
    <h1>Welcome!</h1>
    <p>This page is served by Flask using a template.</p>
</body>
</html>

Now when you open / in your browser, you see this HTML page.

Passing Data from Routes to Templates

Templates become powerful when you send data from your route to the template.

Use render_template("file.html", name=value, ...) to pass values.

Example: passing a name to show in the HTML.

app.py:

from flask import Flask, render_template
app = Flask(__name__)
@app.route("/hello/<name>")
def hello(name):
    return render_template("hello.html", username=name)
if __name__ == "__main__":
    app.run(debug=True)

templates/hello.html:

<!DOCTYPE html>
<html>
<head>
    <title>Hello Page</title>
</head>
<body>
    <h1>Hello, {{ username }}!</h1>
    <p>Nice to see you here.</p>
</body>
</html>

Here:

This {{ ... }} syntax is part of the template language.

Template Syntax Basics

Inserting Variables: `{{ ... }}`

Use double curly braces to print values.

Examples in template.html:

<p>Your name is: {{ name }}</p>
<p>Your age is: {{ age }}</p>
<p>Welcome, {{ user_first_name }} {{ user_last_name }}!</p>

Python route:

@app.route("/user")
def user():
    return render_template(
        "user.html",
        name="Alice",
        age=30,
        user_first_name="Alice",
        user_last_name="Smith"
    )

The template engine replaces {{ ... }} with the actual values.

Simple Logic: `{% ... %}`

You can add simple control structures inside templates using {% ... %}. These are not printed; they control the flow.

Common ones:

`if` Example

Route:

@app.route("/status/<int:score>")
def status(score):
    return render_template("status.html", score=score)

Template status.html:

<!DOCTYPE html>
<html>
<head>
    <title>Status</title>
</head>
<body>
    <h1>Your score: {{ score }}</h1>
    {% if score >= 50 %}
        <p>Congratulations, you passed!</p>
    {% else %}
        <p>Sorry, you did not pass.</p>
    {% endif %}
</body>
</html>
`for` Loop Example

Route:

@app.route("/shopping-list")
def shopping_list():
    items = ["Apples", "Bread", "Milk"]
    return render_template("shopping.html", items=items)

Template shopping.html:

<!DOCTYPE html>
<html>
<head>
    <title>Shopping List</title>
</head>
<body>
    <h1>Shopping List</h1>
    <ul>
        {% for item in items %}
            <li>{{ item }}</li>
        {% endfor %}
    </ul>
</body>
</html>

Here:

Connecting Routing and Templates

Routing and templates work together:

A slightly more complete example:

app.py:

from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def index():
    # some data to show on the homepage
    title = "My Flask Site"
    description = "This is a very simple website built with Flask."
    features = ["Fast", "Simple", "Fun to learn"]
    return render_template(
        "index.html",
        page_title=title,
        page_description=description,
        features=features
    )
if __name__ == "__main__":
    app.run(debug=True)

templates/index.html:

<!DOCTYPE html>
<html>
<head>
    <title>{{ page_title }}</title>
</head>
<body>
    <h1>{{ page_title }}</h1>
    <p>{{ page_description }}</p>
    <h2>Features</h2>
    <ul>
        {% for feature in features %}
            <li>{{ feature }}</li>
        {% endfor %}
    </ul>
</body>
</html>

Visit / to see how routing and templates work together.

Template Inheritance (Basic Idea)

As your site grows, many pages share the same structure:

You don’t want to repeat the same code in every template. Instead, you can:

Simple example (a taste of the idea):

templates/base.html:

<!DOCTYPE html>
<html>
<head>
    <title>{% block title %}My Site{% endblock %}</title>
</head>
<body>
    <header>
        <h1>My Site</h1>
        <nav>
            <a href="{{ url_for('home') }}">Home</a> |
            <a href="{{ url_for('about') }}">About</a>
        </nav>
    </header>
    <main>
        {% block content %}
        <!-- Default content -->
        {% endblock %}
    </main>
    <footer>
        <p>Footer text here</p>
    </footer>
</body>
</html>

templates/home.html:

{% extends "base.html" %}
{% block title %}Home - My Site{% endblock %}
{% block content %}
    <h2>Welcome to the homepage</h2>
    <p>This content is specific to the home page.</p>
{% endblock %}

app.py:

from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def home():
    return render_template("home.html")
@app.route("/about")
def about():
    return render_template("about.html")  # you’d define about.html similarly
if __name__ == "__main__":
    app.run(debug=True)

Here:

This helps keep your templates clean and consistent.

Using `url_for` Inside Templates

Just like in Python code, you can use url_for inside templates to avoid hard-coding links.

Example in base.html:

<nav>
    <a href="{{ url_for('home') }}">Home</a>
    <a href="{{ url_for('about') }}">About</a>
</nav>

Make sure the function names in your routes match:

@app.route("/")
def home():
    return render_template("home.html")
@app.route("/about")
def about():
    return render_template("about.html")

Now if you ever change /about to /info, you only update the route in Python—links in the templates still work because they use url_for('about'), not the raw string /about.

Putting It All Together: A Tiny Multi-Page Site

Folder structure:

my_site/
    app.py
    templates/
        base.html
        home.html
        about.html

app.py:

from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def home():
    features = ["Simple", "Lightweight", "Beginner-friendly"]
    return render_template("home.html", features=features)
@app.route("/about")
def about():
    return render_template("about.html")
if __name__ == "__main__":
    app.run(debug=True)

templates/base.html:

<!DOCTYPE html>
<html>
<head>
    <title>{% block title %}My Flask Site{% endblock %}</title>
</head>
<body>
    <header>
        <h1>My Flask Site</h1>
        <nav>
            <a href="{{ url_for('home') }}">Home</a> |
            <a href="{{ url_for('about') }}">About</a>
        </nav>
    </header>
    <main>
        {% block content %}{% endblock %}
    </main>
    <footer>
        <p>&copy; 2025 My Flask Site</p>
    </footer>
</body>
</html>

templates/home.html:

{% extends "base.html" %}
{% block title %}Home - My Flask Site{% endblock %}
{% block content %}
    <h2>Welcome</h2>
    <p>This is the homepage.</p>
    <h3>Features</h3>
    <ul>
        {% for f in features %}
            <li>{{ f }}</li>
        {% endfor %}
    </ul>
{% endblock %}

templates/about.html:

{% extends "base.html" %}
{% block title %}About - My Flask Site{% endblock %}
{% block content %}
    <h2>About</h2>
    <p>This is a tiny website built with Flask routes and templates.</p>
{% endblock %}

Visiting:

This is the basic pattern you’ll use for building real web applications with Flask: routes decide what data to send, and templates decide how to display it.

Views: 17

Comments

Please login to add a comment.

Don't have an account? Register now!