Files
awesome-copilot/skills/create-web-form/references/python-as-web-framework.md
jhauga 27149859a4 Add skill to create web forms
Add skill to create web forms
2026-02-09 19:22:54 -05:00

13 KiB

Python as Web Framework Reference

Source: https://www.topcoder.com/thrive/articles/python-as-web-framework-the-flask-basics

This reference covers using Python as a web framework through Flask, including setup, routing, templates, request and response handling, form processing, and building practical web applications.


Overview

Flask is a lightweight WSGI (Web Server Gateway Interface) web framework written in Python. It is classified as a micro-framework because it does not require particular tools or libraries. Flask has no database abstraction layer, form validation, or any other components where pre-existing third-party libraries provide common functions.

Why Flask?

  • Lightweight and modular -- only includes what you need
  • Easy to learn -- minimal boilerplate to get started
  • Flexible -- no enforced project structure or dependencies
  • Extensible -- rich ecosystem of extensions for added functionality
  • Well-documented with an active community
  • Built-in development server and debugger

Installation and Setup

Prerequisites

  • Python 3.7+
  • pip (Python package manager)

Install Flask

pip install flask

Verify Installation

import flask
print(flask.__version__)
# Create a virtual environment
python -m venv venv

# Activate (Linux/macOS)
source venv/bin/activate

# Activate (Windows)
venv\Scripts\activate

# Install Flask in the virtual environment
pip install flask

Creating a Basic Flask Application

Hello World

from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello_world():
    return '<h1>Hello, World!</h1>'

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

Understanding the Code

Component Purpose
Flask(__name__) Creates a Flask application instance; __name__ helps Flask locate resources
@app.route('/') A decorator that maps a URL path to a Python function
app.run(debug=True) Starts the development server with auto-reload and debugger

Running the Application

python app.py

The application runs at http://127.0.0.1:5000/ by default.

Debug Mode

Debug mode provides:

  • Auto-reloader -- restarts the server when code changes
  • Interactive debugger -- shows a traceback in the browser with an interactive Python console
  • Detailed error pages -- shows full error details instead of generic "500 Internal Server Error"

Warning: Never enable debug mode in production -- it allows arbitrary code execution.


Routing

Basic Routes

@app.route('/')
def index():
    return 'Index Page'

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

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

Variable Rules (Dynamic URLs)

@app.route('/user/<username>')
def show_user_profile(username):
    return f'User: {username}'

@app.route('/post/<int:post_id>')
def show_post(post_id):
    return f'Post {post_id}'

@app.route('/path/<path:subpath>')
def show_subpath(subpath):
    return f'Subpath: {subpath}'

URL Converters

Converter Description Example
string Accepts any text without slashes (default) /user/<username>
int Accepts positive integers /post/<int:post_id>
float Accepts positive floating-point values /price/<float:amount>
path Accepts text including slashes /file/<path:filepath>
uuid Accepts UUID strings /item/<uuid:item_id>

URL Building with url_for()

from flask import url_for

@app.route('/')
def index():
    return 'Index'

@app.route('/login')
def login():
    return 'Login'

@app.route('/user/<username>')
def profile(username):
    return f'{username} profile'

# Usage:
with app.test_request_context():
    print(url_for('index'))                  # /
    print(url_for('login'))                  # /login
    print(url_for('profile', username='John'))  # /user/John

HTTP Methods

from flask import request

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        return do_the_login()
    else:
        return show_the_login_form()

Templates with Jinja2

Flask uses the Jinja2 template engine for rendering HTML.

Rendering Templates

from flask import render_template

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

Template File (templates/hello.html)

<!DOCTYPE html>
<html>
<head>
    <title>Hello</title>
</head>
<body>
    {% if name %}
        <h1>Hello, {{ name }}!</h1>
    {% else %}
        <h1>Hello, World!</h1>
    {% endif %}
</body>
</html>

Template Syntax

Syntax Purpose Example
{{ ... }} Expression output {{ user.name }}
{% ... %} Statement (control flow) {% if user %}...{% endif %}
{# ... #} Comment (not rendered) {# This is a comment #}

Template Inheritance

Base template (base.html):

<!DOCTYPE html>
<html>
<head>
    <title>{% block title %}Default Title{% endblock %}</title>
</head>
<body>
    <header>
        {% block header %}
            <h1>My Website</h1>
        {% endblock %}
    </header>

    <main>
        {% block content %}{% endblock %}
    </main>

    <footer>
        {% block footer %}
            <p>Footer content</p>
        {% endblock %}
    </footer>
</body>
</html>

Child template (home.html):

{% extends "base.html" %}

{% block title %}Home Page{% endblock %}

{% block content %}
    <h2>Welcome!</h2>
    <p>This is the home page.</p>
{% endblock %}

Loops and Conditionals

<!-- For loop -->
<ul>
{% for item in navigation %}
    <li><a href="{{ item.href }}">{{ item.caption }}</a></li>
{% endfor %}
</ul>

<!-- Conditionals -->
{% if users %}
    <ul>
    {% for user in users %}
        <li>{{ user.username }}</li>
    {% endfor %}
    </ul>
{% else %}
    <p>No users found.</p>
{% endif %}

Request and Response

The Request Object

from flask import request

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

        if valid_login(username, password):
            return log_the_user_in(username)
        else:
            error = 'Invalid username/password'

    return render_template('login.html', error=error)

Request Object Attributes

Attribute Description
request.method The HTTP method (GET, POST, etc.)
request.form Form data from POST/PUT requests
request.args URL query string parameters
request.files Uploaded files
request.cookies Request cookies
request.headers Request headers
request.json Parsed JSON data (if content type is JSON)
request.data Raw request data as bytes
request.url The full URL of the request
request.path The URL path (without query string)

Query String Parameters

# URL: /search?q=flask&page=2
@app.route('/search')
def search():
    query = request.args.get('q', '')
    page = request.args.get('page', 1, type=int)
    return f'Searching for: {query}, Page: {page}'

Responses

from flask import make_response, jsonify

# Simple string response
@app.route('/')
def index():
    return 'Hello World'

# Response with status code
@app.route('/not-found')
def not_found():
    return 'Page Not Found', 404

# Custom response object
@app.route('/custom')
def custom():
    response = make_response('Custom Response')
    response.headers['X-Custom-Header'] = 'custom-value'
    return response

# JSON response
@app.route('/api/data')
def api_data():
    return jsonify({'name': 'Flask', 'version': '2.0'})

Form Handling

HTML Form

<form method="POST" action="/submit">
    <label for="name">Name:</label>
    <input type="text" id="name" name="name" required>

    <label for="email">Email:</label>
    <input type="email" id="email" name="email" required>

    <label for="message">Message:</label>
    <textarea id="message" name="message" required></textarea>

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

Processing Form Data

@app.route('/submit', methods=['GET', 'POST'])
def submit():
    if request.method == 'POST':
        name = request.form.get('name')
        email = request.form.get('email')
        message = request.form.get('message')

        # Validate the data
        if not name or not email or not message:
            return render_template('form.html', error='All fields are required.')

        # Process the data (save to DB, send email, etc.)
        return render_template('success.html', name=name)

    return render_template('form.html')

Static Files

Flask serves static files from the static/ folder by default.

Serving Static Files

<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
<script src="{{ url_for('static', filename='js/main.js') }}"></script>
<img src="{{ url_for('static', filename='images/logo.png') }}" alt="Logo">

Static File Organization

static/
    css/
        style.css
    js/
        main.js
    images/
        logo.png

Sessions and Cookies

Using Sessions

from flask import session

app.secret_key = 'your-secret-key'

@app.route('/login', methods=['POST'])
def login():
    session['username'] = request.form['username']
    return redirect(url_for('index'))

@app.route('/logout')
def logout():
    session.pop('username', None)
    return redirect(url_for('index'))

@app.route('/')
def index():
    if 'username' in session:
        return f'Logged in as {session["username"]}'
    return 'You are not logged in'

Setting Cookies

from flask import make_response

@app.route('/set-cookie')
def set_cookie():
    response = make_response('Cookie set!')
    response.set_cookie('username', 'flask_user', max_age=3600)
    return response

@app.route('/get-cookie')
def get_cookie():
    username = request.cookies.get('username')
    return f'Username: {username}'

Error Handling

Custom Error Pages

@app.errorhandler(404)
def page_not_found(error):
    return render_template('404.html'), 404

@app.errorhandler(500)
def internal_server_error(error):
    return render_template('500.html'), 500

Aborting Requests

from flask import abort

@app.route('/user/<int:user_id>')
def get_user(user_id):
    user = find_user(user_id)
    if user is None:
        abort(404)
    return render_template('user.html', user=user)

Redirects

from flask import redirect, url_for

@app.route('/old-page')
def old_page():
    return redirect(url_for('new_page'))

@app.route('/new-page')
def new_page():
    return 'This is the new page.'

# Redirect with status code
@app.route('/moved')
def moved():
    return redirect(url_for('new_page'), code=301)

Flask Extensions

Common Flask extensions for building web applications:

Extension Purpose
Flask-SQLAlchemy Database ORM integration
Flask-WTF Form handling with WTForms and CSRF protection
Flask-Login User session management and authentication
Flask-Mail Email sending support
Flask-Migrate Database migration management via Alembic
Flask-RESTful Building REST APIs
Flask-CORS Cross-Origin Resource Sharing support
Flask-Caching Response caching
Flask-Limiter Rate limiting for API endpoints

Key Takeaways

  1. Flask is a micro-framework -- it provides the essentials (routing, templates, request handling) and lets you choose extensions for everything else.
  2. Routing maps URLs to functions using the @app.route() decorator with support for dynamic URL parameters and multiple HTTP methods.
  3. Jinja2 templates support inheritance, loops, conditionals, and variable output for building dynamic HTML pages.
  4. The request object gives access to form data, query parameters, headers, cookies, and uploaded files.
  5. Use url_for() to build URLs dynamically instead of hard-coding paths.
  6. Debug mode is essential for development but must be disabled in production.
  7. Virtual environments isolate project dependencies and should always be used.
  8. Static files are served from the static/ directory and referenced using url_for('static', filename='...').
  9. Sessions provide server-side user state management, requiring a SECRET_KEY configuration.
  10. Flask extensions provide modular functionality for databases, forms, authentication, email, and more.