Lesson 69 · Web Development

Python Flask

Learn how to build web applications and APIs with Flask, a lightweight and flexible Python web framework used for everything from small applications to production services.

50–60 minutes Intermediate Web Development
0%
01

Learning Objectives

Flask introduces an important new stage in your Python journey: building applications that communicate through the web.

By the end of this lesson, you will be able to:

  • Understand what Flask is and why it is useful.
  • Install Flask inside a Python environment.
  • Create your first Flask application.
  • Understand routes and URLs.
  • Work with HTTP methods.
  • Use dynamic route parameters.
  • Read query parameters and form data.
  • Render HTML templates using Jinja.
  • Serve CSS, JavaScript, and other static files.
  • Return text and JSON responses.
  • Use redirects, sessions, and error handlers.
  • Organize a small Flask project professionally.
02

What Is Flask?

Flask is a lightweight web framework written in Python.

It provides the fundamental tools required to receive HTTP requests, execute Python code, and return responses to users.

Simple idea

A Flask application can receive a request such as /products, execute Python logic, and return HTML, JSON, or another response.

Flask is often described as a microframework because its core is intentionally small and flexible.

You can add additional libraries and components depending on what your application needs.

03

What Is a Web Framework?

A web framework provides tools and conventions that make building web applications easier.

Without a framework, you would need to handle many low-level web details yourself.

Flask helps with:

  • Receiving HTTP requests
  • Routing URLs to Python functions
  • Returning HTTP responses
  • Rendering HTML templates
  • Handling forms
  • Managing sessions
  • Returning JSON
  • Handling errors

Flask does not force you into one large application architecture. This flexibility makes it useful for learning as well as building many types of web applications.

04

Installing Flask

Flask should normally be installed inside a virtual environment for your project.

python -m pip install flask

Verify that Flask is available:

python -m pip show flask

Recommended practice

Use a virtual environment so that your Flask project's dependencies remain isolated from other Python projects.

05

Your First Flask Application

Create a file named app.py.

from flask import Flask

app = Flask(__name__)

@app.route("/")
def home():
    return "Hello, PyLearn!"

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

Understanding the Code

  • Flask is imported from the Flask package.
  • Flask(__name__) creates the application.
  • @app.route("/") connects the root URL to the home() function.
  • The function returns the response.
  • app.run() starts the development server.

Your first web route

When you visit the application's root URL, Flask executes home() and sends its returned text to the browser.

06

Running the Development Server

From the project directory, run:

python app.py

Flask will start a local development server.

You will normally see an address similar to:

http://127.0.0.1:5000

Development server warning

Flask's built-in development server is intended for development and testing, not as the production server for a deployed application.

The debug=True option enables useful development features such as automatic reloading and detailed error information.

07

Routes

A route maps a URL to a Python function.

@app.route("/")
def home():
    return "Home Page"


@app.route("/about")
def about():
    return "About Page"


@app.route("/contact")
def contact():
    return "Contact Page"

Now the application has three different URLs.

  • / → Home
  • /about → About
  • /contact → Contact

Routes are one of the central concepts of Flask.

08

HTTP Methods

HTTP defines several methods that describe what the client wants to do.

  • GET — retrieve information.
  • POST — submit or create information.
  • PUT — replace an existing resource.
  • PATCH — partially update a resource.
  • DELETE — remove a resource.

GET Route

@app.route("/products", methods=["GET"])
def products():
    return "Product List"

POST Route

@app.route("/products", methods=["POST"])
def create_product():
    return "Product Created"

A single route can also support multiple methods.

@app.route(
    "/products",
    methods=["GET", "POST"]
)
def product_handler():

    if request.method == "GET":
        return "Get Products"

    return "Create Product"

When using request, remember to import it:

from flask import Flask, request
09

Route Parameters

Dynamic route parameters allow part of the URL to become input for your Python function.

@app.route("/user/<username>")
def user_profile(username):
    return f"Welcome, {username}!"

Visiting a URL such as:

/user/Ali

passes "Ali" into the function.

Integer Parameters

@app.route("/product/<int:product_id>")
def product(product_id):
    return f"Product ID: {product_id}"

Common converters

  • <string:name>
  • <int:id>
  • <float:price>
  • <path:subpath>
10

Query Parameters

Query parameters appear after a question mark in a URL.

/products?category=phones&page=2

Flask provides the request object for reading them.

from flask import Flask, request

@app.route("/products")
def products():

    category = request.args.get("category")
    page = request.args.get("page", default=1, type=int)

    return f"Category: {category}, Page: {page}"

request.args.get() is useful because you can provide a default value when a parameter is missing.

11

Returning Responses

Flask routes can return different kinds of responses.

Text

@app.route("/hello")
def hello():
    return "Hello World!"

HTML

@app.route("/welcome")
def welcome():
    return "<h1>Welcome to PyLearn</h1>"

For real applications, HTML should normally be placed in templates rather than embedded directly in Python strings.

12

HTML Templates

Flask uses a templates directory for HTML templates.

A simple project may look like:

project/
│
├── app.py
│
└── templates/
    └── index.html

Create index.html:

<!DOCTYPE html>
<html>
<head>
    <title>PyLearn Flask App</title>
</head>
<body>

    <h1>Welcome to PyLearn</h1>

</body>
</html>

Render it from Flask:

from flask import Flask, render_template

app = Flask(__name__)

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

Jinja Templates

Flask uses the Jinja template engine to generate dynamic HTML.

Jinja allows Python-generated values to be inserted into HTML templates.

Variable Example

<h1>Hello, {{ name }}!</h1>

Flask:

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

Conditional Template Logic

{% if logged_in %}
    <p>Welcome back!</p>
{% else %}
    <p>Please log in.</p>
{% endif %}

Loops

<ul>

{% for product in products %}

    <li>
        {{ product }}
    </li>

{% endfor %}

</ul>

Important distinction

Jinja syntax resembles Python in some places, but template code is not simply Python pasted into HTML. Jinja has its own template syntax.

14

Passing Data to Templates

Flask can pass Python variables into an HTML template.

@app.route("/products")
def products():

    products = [
        "Laptop",
        "Phone",
        "Tablet"
    ]

    return render_template(
        "products.html",
        products=products
    )

The template can then loop through the data.

<h1>Products</h1>

<ul>

{% for product in products %}

    <li>{{ product }}</li>

{% endfor %}

</ul>
15

Static Files

Web applications commonly contain CSS, JavaScript, images, and other files that do not need to be generated dynamically.

Flask conventionally stores these in a static directory.

project/
│
├── app.py
│
├── templates/
│   └── index.html
│
└── static/
    ├── css/
    │   └── style.css
    │
    └── js/
        └── script.js

In the template:

<link
    rel="stylesheet"
    href="{{ url_for('static', filename='css/style.css') }}"
>

Flask's url_for() function generates the appropriate URL for the static file.

16

HTML Forms

Forms allow users to send information to a web application.

<form method="POST">

    <input
        type="text"
        name="username"
        placeholder="Enter your name"
    >

    <button type="submit">
        Submit
    </button>

</form>

Flask can receive the submitted form data.

from flask import Flask, request

@app.route("/login", methods=["GET", "POST"])
def login():

    if request.method == "POST":

        username = request.form.get("username")

        return f"Hello, {username}"

    return render_template("login.html")

Security matters

Real authentication systems require password hashing, secure sessions, CSRF protection, validation, and other security measures. Never store plaintext passwords.

17

The request Object

Flask's request object contains information about the incoming HTTP request.

from flask import request

Useful request attributes

  • request.method — HTTP method.
  • request.args — query parameters.
  • request.form — submitted form data.
  • request.json — JSON request body.
  • request.files — uploaded files.
  • request.headers — HTTP headers.

Understanding the request object becomes particularly important when building APIs.

18

Redirects & URLs

A redirect tells the browser to visit another URL.

from flask import redirect, url_for

@app.route("/old")
def old_page():
    return redirect(url_for("home"))

url_for() is useful because it generates URLs from endpoint names instead of manually constructing paths.

Why use url_for()?

If your URL structure changes later, generating URLs through Flask is safer and easier to maintain than hard-coding paths throughout your application.

19

Returning JSON

Flask can return JSON data, which is essential when building APIs.

from flask import jsonify

@app.route("/api/products")
def api_products():

    products = [
        {
            "id": 1,
            "name": "Laptop",
            "price": 1200
        },
        {
            "id": 2,
            "name": "Phone",
            "price": 800
        }
    ]

    return jsonify(products)

A client such as JavaScript, a mobile application, or another Python program can consume this JSON.

Flask and APIs

This is one reason Flask is useful beyond traditional HTML websites. It can also serve as a backend API.

20

Error Handling

Web applications should handle common HTTP errors gracefully.

from flask import Flask

@app.errorhandler(404)
def page_not_found(error):
    return "Page not found", 404

The second value in the returned tuple is the HTTP status code.

Example

return {
    "error": "Product not found"
}, 404

Returning the correct status code allows clients to understand what happened.

  • 200 — successful request.
  • 201 — resource created.
  • 400 — bad request.
  • 401 — authentication required.
  • 403 — forbidden.
  • 404 — resource not found.
  • 500 — server-side error.
21

Sessions

Sessions allow an application to remember information between requests for a user.

from flask import Flask, session

app = Flask(__name__)

app.secret_key = "change-this-in-a-real-project"

@app.route("/login")
def login():

    session["username"] = "Ali"

    return "Logged in"

The stored value can later be retrieved:

@app.route("/profile")
def profile():

    username = session.get("username")

    return f"User: {username}"

Never expose secret keys

In real applications, secret keys should not be hard-coded into publicly shared source code. Use environment variables or a secure configuration system.

22

Professional Flask Project Structure

As applications grow, keeping everything in one Python file becomes difficult.

A small Flask application may start like this:

my_flask_app/
│
├── app.py
│
├── templates/
│   ├── index.html
│   ├── products.html
│   └── login.html
│
└── static/
    ├── css/
    │   └── style.css
    │
    ├── js/
    │   └── script.js
    │
    └── images/

Larger Flask applications can later use application factories, blueprints, configuration modules, services, database layers, and separate packages.

Start simple, scale deliberately

You do not need a complicated architecture for a small project. Good structure should grow as the application's complexity grows.

23

Flask & Databases

Real web applications frequently need persistent data such as users, products, orders, payments, and inventory.

Flask itself does not force you to use one particular database.

Common choices

  • SQLite
  • PostgreSQL
  • MySQL
  • Other database systems through appropriate libraries

You have already learned SQLite earlier in this course. That knowledge can now be connected with Flask to create database-driven web applications.

Conceptual Flow

Browser
   ↓
Flask Route
   ↓
Python Logic
   ↓
Database
   ↓
Python Result
   ↓
HTML / JSON Response
   ↓
Browser
24

Practical Example — Product Catalog

Let's create a small Flask application that displays an ecommerce product catalog.

app.py

from flask import Flask, render_template

app = Flask(__name__)

products = [
    {
        "name": "Laptop",
        "price": 1200
    },
    {
        "name": "Phone",
        "price": 800
    },
    {
        "name": "Tablet",
        "price": 500
    }
]


@app.route("/")
def home():
    return render_template(
        "products.html",
        products=products
    )


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

templates/products.html

<!DOCTYPE html>
<html lang="en">

<head>

    <meta charset="UTF-8">

    <title>Product Catalog</title>

</head>

<body>

    <h1>Product Catalog</h1>

    <ul>

        {% for product in products %}

            <li>

                <strong>
                    {{ product.name }}
                </strong>

                - ${{ product.price }}

            </li>

        {% endfor %}

    </ul>

</body>

</html>

Flask sends the Python list to Jinja, and Jinja generates the HTML for each product.

Ecommerce connection

This same concept can eventually become a real ecommerce backend where products are loaded from a database, customers submit orders, and APIs communicate with frontend applications.

25

Common Flask Mistakes

Mistake 1 — Wrong project structure

Flask expects templates and static files in their conventional locations unless you explicitly configure different paths.

Mistake 2 — Forgetting the route decorator

A Python function does not automatically become a web endpoint. It needs to be connected to a route.

Mistake 3 — Wrong HTTP method

A route designed for POST requests cannot be used as though it only accepts GET requests.

Mistake 4 — Hard-coding URLs everywhere

Use url_for() where appropriate instead of manually repeating URL paths throughout templates.

Mistake 5 — Exposing secrets

API keys, passwords, secret keys, and database credentials should not be committed directly into source code.

Mistake 6 — Using debug mode in production

Debug mode is useful during development but should not be treated as a production deployment configuration.

Mistake 7 — Trusting user input

User-submitted data must be validated and handled safely. Never assume browser input is trustworthy.

26

Practice Exercises

Exercise 1 — Hello Flask

Create a Flask application with a root route that returns a welcome message.

Exercise 2 — Multiple Pages

Create /, /about, and /contact routes.

Exercise 3 — Dynamic Route

Create a route such as /student/<name> and display the student's name.

Exercise 4 — Query Parameters

Create a product search route that reads a keyword query parameter.

Exercise 5 — HTML Template

Create an HTML template and render it using render_template().

Exercise 6 — Product List

Pass a Python list of products into a Jinja template and display them using a loop.

27

Mini Challenge — Flask Ecommerce Catalog

Build a small Flask ecommerce catalog that demonstrates the concepts from this lesson.

Your Tasks

  1. Create a Flask application.
  2. Create a / route for the homepage.
  3. Create a /products route.
  4. Store at least five products in a Python list.
  5. Display products using a Jinja template.
  6. Include product name, price, and category.
  7. Create a dynamic route: /product/<int:id>.
  8. Create a search route using a query parameter.
  9. Add CSS using the static directory.
  10. Add an API endpoint such as /api/products.
  11. Return the products from the API as JSON.
  12. Add a custom 404 page or error response.

Suggested Starting Point

from flask import (
    Flask,
    render_template,
    request,
    jsonify
)

app = Flask(__name__)

products = [
    {
        "id": 1,
        "name": "Laptop",
        "price": 1200,
        "category": "Electronics"
    },
    {
        "id": 2,
        "name": "Phone",
        "price": 800,
        "category": "Electronics"
    },
    {
        "id": 3,
        "name": "Tablet",
        "price": 500,
        "category": "Electronics"
    },
    {
        "id": 4,
        "name": "Backpack",
        "price": 80,
        "category": "Accessories"
    },
    {
        "id": 5,
        "name": "Headphones",
        "price": 120,
        "category": "Accessories"
    }
]


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


@app.route("/products")
def product_list():

    keyword = request.args.get(
        "keyword"
    )

    filtered = products

    if keyword:
        filtered = [
            product
            for product in products
            if keyword.lower()
            in product["name"].lower()
        ]

    return render_template(
        "products.html",
        products=filtered
    )


@app.route("/api/products")
def api_products():

    return jsonify(products)


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

Challenge goal

Try to make your application feel like a real small ecommerce backend rather than simply completing isolated Flask exercises.

28

Knowledge Check

Test your understanding of Flask before moving forward.

1. What is Flask?

2. Which decorator connects a function to a URL?

3. Which command installs Flask?

4. What is render_template() used for?

5. Which template engine does Flask commonly use?

6. Where are Flask HTML templates conventionally stored?

7. Which object provides information about an incoming request?

8. Which Flask function is commonly used to return JSON?

9. What is url_for() useful for?

10. Is Flask's built-in development server intended as a production server?

29

Lesson Summary

Flask brings Python into web development. You can now connect Python functions to URLs, receive user requests, generate HTML, and return JSON.

Key concepts to remember

  • Flask is a lightweight Python web framework.
  • Flask(__name__) creates the application.
  • @app.route() connects URLs to functions.
  • HTTP methods describe how clients interact with resources.
  • Route parameters make URLs dynamic.
  • Query parameters can be accessed through request.args.
  • Form data can be accessed through request.form.
  • render_template() renders HTML templates.
  • Jinja allows dynamic data and logic inside templates.
  • Static files belong in the static directory.
  • jsonify() is useful for API responses.
  • url_for() generates endpoint URLs.
  • Sessions can maintain information between requests.
  • Flask applications can connect to databases such as SQLite.

What's next?

Flask introduced you to synchronous web applications. In the next lesson, you will learn FastAPI, a modern Python framework particularly well suited to APIs, type hints, and asynchronous applications.

Ready for the next lesson?

Mark this lesson complete when you can create a basic Flask application, define routes, render templates, and return JSON.