We use cookies to enhance your experience on the site
CodeWorlds

Flask - web microframework

Welcome back, @name! Darwin here, ready to show you Flask - the most popular web microframework in Python! 🐍🌐

In the previous lesson you learned frontend basics (HTML, CSS, JavaScript). Now we'll combine that with Python using Flask! πŸ”—

Safari Analogy: Flask is like a mobile research center - lightweight, flexible, you can easily move it anywhere and quickly start observations! You don't need a huge laboratory (Django) to begin research. πŸšπŸ”¬

What is Flask?

Flask is a microframework for web development written in Python by Armin Ronacher in 2010.

Microframework = a minimalist framework with basic features that you can extend with plugins.

Flask vs Django

| Flask | Django | |-------|--------| | Microframework - minimalist | Full-stack framework - all-in-one | | Flexible, modular | Opinionated, conventions | | Great for small/medium projects | Great for large projects | | You choose components yourself | Everything out-of-the-box | | ~10 lines for Hello World | ~50 lines for Hello World | | Great for learning! | More complex |

Analogy: Flask is a research tent (quick setup), Django is a full laboratory (long configuration, but all tools included). πŸ•οΈπŸ’

Why use Flask?

βœ… Simple - minimal learning curve βœ… Flexible - you choose the components βœ… Lightweight - small app, fast start βœ… Pythonic - clean, readable code βœ… Great documentation - easy to learn βœ… Large community - plenty of plugins

Flask use cases:

  • πŸ”¬ Prototypes and MVPs
  • πŸ“Š Dashboards and admin panels
  • πŸ€– APIs for mobile apps
  • πŸ“ˆ Data visualizations
  • πŸ§ͺ Educational projects

Installing Flask

Flask is installed via `pip` like any Python package.

Step 1: Create a virtual environment

Always use a virtual environment for Python projects!

1# Create project folder
2mkdir safari_web
3cd safari_web
4
5# Create virtual environment
6python -m venv venv
7
8# Activate environment
9# Windows:
10venv\\Scripts\\activate
11# Mac/Linux:
12source venv/bin/activate

Analogy: A virtual environment is like a separate enclosure for your project - libraries from one project won't conflict with others! 🦁🐘

Step 2: Install Flask

1# Install Flask
2pip install Flask
3
4# Check version
5flask --version
6# Output: Python 3.11.0
7#         Flask 3.0.0
8#         Werkzeug 3.0.0

Flask automatically installs:

  • Werkzeug - WSGI utility library (routing, debugging)
  • Jinja2 - template engine (dynamic HTML)
  • MarkupSafe - safe HTML rendering
  • ItsDangerous - secure data signing
  • Click - CLI framework

Step 3: Create requirements.txt

1# Save dependencies
2pip freeze > requirements.txt
3
4# Contents of requirements.txt:
5Flask==3.0.0
6Werkzeug==3.0.0
7Jinja2==3.1.2
8...

Why? Other developers can install the same versions:

1pip install -r requirements.txt

First Flask application - Hello World

Time for your first Flask program! We'll create a page displaying "Hello Safari!" 🦁

Step 1: Create app.py

1# app.py
2from flask import Flask
3
4# Create Flask application instance
5app = Flask(__name__)
6
7# Define a route (URL address)
8@app.route('/')
9def hello():
10    return "Hello Safari! 🦁"
11
12# Run the development server
13if __name__ == '__main__':
14    app.run(debug=True)

What's happening?

  1. `Flask(name)` - creates an application instance

    • `name` is the module name (Flask uses this to locate resources)
  2. `@app.route('/')` - decorator defining a route (URL path)

    • `/` = home page
    • When a user visits `http://localhost:5000/`, the `hello()` function executes
  3. `def hello()` - view function

    • Returns content that will be displayed to the user
  4. `app.run(debug=True)` - starts the development server

    • `debug=True` enables debug mode (auto-reload, detailed errors)

Step 2: Run the application

1python app.py

Output:

1 * Serving Flask app 'app'
2 * Debug mode: on
3WARNING: This is a development server. Do not use it in a production deployment.
4 * Running on http://127.0.0.1:5000
5Press CTRL+C to quit
6 * Restarting with stat
7 * Debugger is active!

Step 3: Open in browser

Go to: http://localhost:5000/

You'll see: Hello Safari! 🦁

Congratulations! You just created your first Flask application! πŸŽ‰

Anatomy of a Flask application

Let's analyze in more detail how Flask works.

1. Application instance

1from flask import Flask
2
3app = Flask(__name__)

`Flask(name)` creates an application object:

  • `name` = module name (e.g. `'main'` or `'app'`)
  • Flask uses this to locate templates, static files

2. Routes (URL paths)

Route = mapping URL β†’ function

1@app.route('/species')
2def list_species():
3    return "List of all species"
4
5@app.route('/species/lion')
6def show_lion():
7    return "Lion details"

How it works?

  • User visits `/species` β†’ `list_species()` executes
  • User visits `/species/lion` β†’ `show_lion()` executes

Analogy: A route is like a safari trail - each trail leads to a different habitat (view function)! πŸ›€οΈπŸ¦

3. View functions

View function = a function that returns an HTTP response

1@app.route('/')
2def home():
3    return "<h1>Safari Database</h1><p>Welcome to the system!</p>"

What can you return?

  • String - will be converted to HTML
  • HTML - rendered in the browser
  • JSON - for API (`jsonify()`)
  • Template - dynamic HTML with Jinja2

4. Running the server

1if __name__ == '__main__':
2    app.run(debug=True)

Parameters of `app.run()`:

  • `debug=True` - debug mode (auto-reload, debugger)
  • `host='0.0.0.0'` - accessible from other devices
  • `port=5000` - port number (default 5000)

⚠️ IMPORTANT: NEVER use `debug=True` in production!

Safari Database - first application

Let's create a simple Safari Database application with several routes! πŸ¦πŸ“Š

app.py - full application

1# app.py
2from flask import Flask
3
4app = Flask(__name__)
5
6# Test data
7species = [
8    {"id": 1, "name": "Lion", "scientific_name": "Panthera leo", "population": 120},
9    {"id": 2, "name": "African Elephant", "scientific_name": "Loxodonta africana", "population": 450},
10    {"id": 3, "name": "Cheetah", "scientific_name": "Acinonyx jubatus", "population": 7100},
11]
12
13# Route 1: Home page
14@app.route('/')
15def home():
16    html = """
17    <!DOCTYPE html>
18    <html>
19    <head>
20        <title>Safari Database</title>
21        <style>
22            body {
23                font-family: Arial, sans-serif;
24                max-width: 800px;
25                margin: 50px auto;
26                padding: 20px;
27                background-color: #f4f1de;
28            }
29            h1 { color: #2c5f2d; }
30            nav { margin: 20px 0; }
31            nav a {
32                margin-right: 15px;
33                color: #2c5f2d;
34                text-decoration: none;
35                font-weight: bold;
36            }
37            nav a:hover { text-decoration: underline; }
38        </style>
39    </head>
40    <body>
41        <h1>🦁 Safari Database 🐘</h1>
42        <p>African species data management system</p>
43
44        <nav>
45            <a href="/">Home</a>
46            <a href="/species">Species list</a>
47            <a href="/about">About</a>
48        </nav>
49
50        <h2>Welcome to Safari Database!</h2>
51        <p>The database contains <strong>{} species</strong>.</p>
52        <p><a href="/species">See full species list β†’</a></p>
53    </body>
54    </html>
55    """.format(len(species))
56
57    return html
58
59# Route 2: Species list
60@app.route('/species')
61def list_species():
62    species_html = ""
63    for spec in species:
64        species_html += f"""
65        <div style="background: white; padding: 15px; margin: 10px 0; border-radius: 8px; border-left: 4px solid #2c5f2d;">
66            <h3>{spec['name']}</h3>
67            <p><strong>Scientific name:</strong> {spec['scientific_name']}</p>
68            <p><strong>Population:</strong> {spec['population']} individuals</p>
69            <a href="/species/{spec['id']}">See details β†’</a>
70        </div>
71        """
72
73    html = f"""
74    <!DOCTYPE html>
75    <html>
76    <head>
77        <title>Species list - Safari Database</title>
78        <style>
79            body {{
80                font-family: Arial, sans-serif;
81                max-width: 800px;
82                margin: 50px auto;
83                padding: 20px;
84                background-color: #f4f1de;
85            }}
86            h1 {{ color: #2c5f2d; }}
87            nav {{ margin: 20px 0; }}
88            nav a {{
89                margin-right: 15px;
90                color: #2c5f2d;
91                text-decoration: none;
92                font-weight: bold;
93            }}
94            nav a:hover {{ text-decoration: underline; }}
95        </style>
96    </head>
97    <body>
98        <h1>🦁 Species list</h1>
99
100        <nav>
101            <a href="/">Home</a>
102            <a href="/species">Species list</a>
103            <a href="/about">About</a>
104        </nav>
105
106        <p>Total: <strong>{len(species)} species</strong></p>
107
108        {species_html}
109
110        <p><a href="/">← Back to home page</a></p>
111    </body>
112    </html>
113    """
114
115    return html
116
117# Route 3: Species details (dynamic URL)
118@app.route('/species/<int:species_id>')
119def show_species(species_id):
120    # Find species by ID
121    spec = next((s for s in species if s['id'] == species_id), None)
122
123    if spec is None:
124        return "<h1>404 - Species not found</h1><a href='/species'>Back to list</a>", 404
125
126    html = f"""
127    <!DOCTYPE html>
128    <html>
129    <head>
130        <title>{spec['name']} - Safari Database</title>
131        <style>
132            body {{
133                font-family: Arial, sans-serif;
134                max-width: 800px;
135                margin: 50px auto;
136                padding: 20px;
137                background-color: #f4f1de;
138            }}
139            h1 {{ color: #2c5f2d; }}
140            .card {{
141                background: white;
142                padding: 30px;
143                border-radius: 12px;
144                border: 3px solid #2c5f2d;
145            }}
146        </style>
147    </head>
148    <body>
149        <h1>🦁 {spec['name']}</h1>
150
151        <div class="card">
152            <h2>{spec['name']}</h2>
153            <p><strong>Scientific name:</strong> <em>{spec['scientific_name']}</em></p>
154            <p><strong>Population:</strong> {spec['population']} individuals</p>
155            <p><strong>System ID:</strong> {spec['id']}</p>
156        </div>
157
158        <p style="margin-top: 20px;">
159            <a href="/species">← Back to species list</a> |
160            <a href="/">← Home page</a>
161        </p>
162    </body>
163    </html>
164    """
165
166    return html
167
168# Route 4: About the system
169@app.route('/about')
170def about():
171    html = """
172    <!DOCTYPE html>
173    <html>
174    <head>
175        <title>About - Safari Database</title>
176        <style>
177            body {
178                font-family: Arial, sans-serif;
179                max-width: 800px;
180                margin: 50px auto;
181                padding: 20px;
182                background-color: #f4f1de;
183            }
184            h1 { color: #2c5f2d; }
185        </style>
186    </head>
187    <body>
188        <h1>🦁 About Safari Database</h1>
189
190        <p><strong>Safari Database</strong> is an African species data management system.</p>
191
192        <h2>Technologies:</h2>
193        <ul>
194            <li>Flask 3.0 - web microframework</li>
195            <li>Python 3.11 - programming language</li>
196            <li>HTML/CSS - frontend</li>
197        </ul>
198
199        <h2>Features:</h2>
200        <ul>
201            <li>Browse species list</li>
202            <li>Details for each species</li>
203            <li>Population statistics</li>
204        </ul>
205
206        <p><a href="/">← Back to home page</a></p>
207    </body>
208    </html>
209    """
210
211    return html
212
213# Run development server
214if __name__ == '__main__':
215    print("🦁 Safari Database starting...")
216    print("πŸ“‘ Server available at: http://localhost:5000/")
217    app.run(debug=True)

Testing the application

1python app.py

Open in browser:

  • http://localhost:5000/ - home page
  • http://localhost:5000/species - species list
  • http://localhost:5000/species/1 - lion details
  • http://localhost:5000/species/2 - elephant details
  • http://localhost:5000/about - about the system

Also check errors:

  • http://localhost:5000/species/999 - species doesn't exist (404)

Dynamic URLs - parameters

Flask allows dynamic URLs with parameters:

1# Basic parameter (string)
2@app.route('/user/<username>')
3def show_user(username):
4    return f"User: {username}"
5
6# Int type parameter
7@app.route('/species/<int:species_id>')
8def show_species(species_id):
9    return f"Species ID: {species_id}"
10
11# Float type parameter
12@app.route('/price/<float:price>')
13def show_price(price):
14    return f"Price: {price:.2f}"
15
16# Path parameter (can contain /)
17@app.route('/file/<path:filepath>')
18def show_file(filepath):
19    return f"File: {filepath}"

Converter types:

  • `string` - accepts text without slash (default)
  • `int` - accepts integers
  • `float` - accepts floating point numbers
  • `path` - like string, but accepts slashes
  • `uuid` - accepts UUID strings

URL examples:

1/user/darwin           β†’ username="darwin"
2/species/42            β†’ species_id=42
3/price/19.99           β†’ price=19.99
4/file/images/lion.jpg  β†’ filepath="images/lion.jpg"

HTTP Methods - GET and POST

Flask by default handles only GET requests. You can add other methods:

1from flask import request
2
3# GET only (default)
4@app.route('/species')
5def list_species():
6    return "Species list (GET)"
7
8# GET and POST
9@app.route('/species', methods=['GET', 'POST'])
10def species():
11    if request.method == 'POST':
12        # Handle form
13        name = request.form['name']
14        return f"Species added: {name}"
15    else:
16        # Display form
17        return """
18        <form method="POST">
19            <input type="text" name="name" placeholder="Species name">
20            <button type="submit">Add</button>
21        </form>
22        """
23
24# POST only
25@app.route('/api/species', methods=['POST'])
26def create_species():
27    return "Species created (POST only)"

HTTP Methods:

  • GET - retrieve data (default, safe)
  • POST - send data (forms, creation)
  • PUT - update data (full update)
  • PATCH - partial update
  • DELETE - delete data

Debugging and Auto-reload

Debug mode (`debug=True`) enables:

1. Auto-reload

The server automatically restarts after code changes!

1app.run(debug=True)

Test it:

  1. Run `python app.py`
  2. Change something in the code (e.g. text in a route)
  3. Save the file
  4. Flask automatically reloads the application! ♻️

2. Interactive debugger

When an error occurs, Flask shows an interactive debugger in the browser:

1@app.route('/error')
2def error():
3    result = 10 / 0  # Error: division by zero!
4    return "This won't be reached"

Visit `/error` β†’ you'll see a detailed traceback with the ability to inspect variables!

3. Detailed error messages

Flask shows exact error information instead of a generic "500 Internal Server Error".

⚠️ IMPORTANT: NEVER use `debug=True` in production - it shows source code and allows code execution!

Flask CLI - alternative way to run

Instead of `python app.py` you can use Flask CLI:

1# Set environment variable
2export FLASK_APP=app.py
3export FLASK_DEBUG=1  # Enable debug mode
4
5# Run server
6flask run
7
8# Run on different port
9flask run --port 8000
10
11# Accessible from other devices
12flask run --host=0.0.0.0

Windows (PowerShell):

1$env:FLASK_APP = "app.py"
2$env:FLASK_DEBUG = "1"
3flask run

Flask project structure

A simple Flask project can look like this:

1safari_web/
2β”‚
3β”œβ”€β”€ venv/              # Virtual environment (don't commit to git!)
4β”‚
5β”œβ”€β”€ app.py             # Main application
6β”‚
7β”œβ”€β”€ requirements.txt   # Dependencies (pip freeze)
8β”‚
9β”œβ”€β”€ static/            # Static files (CSS, JS, images)
10β”‚   β”œβ”€β”€ css/
11β”‚   β”‚   └── style.css
12β”‚   β”œβ”€β”€ js/
13β”‚   β”‚   └── script.js
14β”‚   └── images/
15β”‚       └── logo.png
16β”‚
17β”œβ”€β”€ templates/         # HTML templates (Jinja2)
18β”‚   β”œβ”€β”€ base.html
19β”‚   β”œβ”€β”€ home.html
20β”‚   └── species.html
21β”‚
22└── .gitignore         # Ignore venv/, __pycache__/, etc.

In the next lesson we'll learn to use templates instead of hardcoded HTML strings! 🎨

Summary

In this lesson you learned:

  • βœ… What Flask is and why to use it
  • βœ… Installing Flask (`pip install Flask`)
  • βœ… First Flask program (Hello World)
  • βœ… Anatomy of a Flask application (app, routes, view functions)
  • βœ… Creating multiple routes
  • βœ… Dynamic URLs with parameters
  • βœ… Debug mode and auto-reload
  • βœ… Flask project structure

Final Safari Analogy: Flask is a mobile research center - lightweight, sets up quickly, you can start observations in minutes! You don't need a huge laboratory (Django) to begin Safari research! πŸšπŸ”¬

Safari Database application code

You created a functioning web application with:

  • πŸ“„ 4 routes (home, species list, species details, about)
  • πŸ”— Dynamic URLs (`/species/int:species_id`)
  • 🎨 HTML + inline CSS
  • 🦁 Test data (species list)

Next lesson: Darwin will show you routing and view functions - advanced techniques for creating routes, redirects, error handlers! πŸ›€οΈπŸ”€

Go to CodeWorlds→