# Python as Web Framework Reference > Source: 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 ```bash pip install flask ``` ### Verify Installation ```python import flask print(flask.__version__) ``` ### Virtual Environment (Recommended) ```bash # 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 ```python from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return '

Hello, World!

' 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 ```bash 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 ```python @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) ```python @app.route('/user/') def show_user_profile(username): return f'User: {username}' @app.route('/post/') def show_post(post_id): return f'Post {post_id}' @app.route('/path/') def show_subpath(subpath): return f'Subpath: {subpath}' ``` ### URL Converters | Converter | Description | Example | |-----------|-------------|---------| | `string` | Accepts any text without slashes (default) | `/user/` | | `int` | Accepts positive integers | `/post/` | | `float` | Accepts positive floating-point values | `/price/` | | `path` | Accepts text including slashes | `/file/` | | `uuid` | Accepts UUID strings | `/item/` | ### URL Building with `url_for()` ```python from flask import url_for @app.route('/') def index(): return 'Index' @app.route('/login') def login(): return 'Login' @app.route('/user/') 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 ```python 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 ```python from flask import render_template @app.route('/hello/') @app.route('/hello/') def hello(name=None): return render_template('hello.html', name=name) ``` ### Template File (`templates/hello.html`) ```html Hello {% if name %}

Hello, {{ name }}!

{% else %}

Hello, World!

{% endif %} ``` ### 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`):** ```html {% block title %}Default Title{% endblock %}
{% block header %}

My Website

{% endblock %}
{% block content %}{% endblock %}
{% block footer %}

Footer content

{% endblock %}
``` **Child template (`home.html`):** ```html {% extends "base.html" %} {% block title %}Home Page{% endblock %} {% block content %}

Welcome!

This is the home page.

{% endblock %} ``` ### Loops and Conditionals ```html {% if users %}
    {% for user in users %}
  • {{ user.username }}
  • {% endfor %}
{% else %}

No users found.

{% endif %} ``` --- ## Request and Response ### The Request Object ```python 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 ```python # 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 ```python 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 ```html
``` ### Processing Form Data ```python @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 ```html Logo ``` ### Static File Organization ``` static/ css/ style.css js/ main.js images/ logo.png ``` --- ## Sessions and Cookies ### Using Sessions ```python 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 ```python 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 ```python @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 ```python from flask import abort @app.route('/user/') def get_user(user_id): user = find_user(user_id) if user is None: abort(404) return render_template('user.html', user=user) ``` --- ## Redirects ```python 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.