Flask-light web frame

онлайн тренажер по питону
Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

What is Flask – a comprehensive guide to the Python web framework

Introduction to Flask

Flask — a minimalist web framework in Python designed for building web applications and REST APIs. It provides a simple and flexible structure that allows rapid development of both prototypes and full‑featured web applications. Flask is built on the WSGI toolkit Werkzeug and uses the Jinja2 templating system.

Created by Armin Ronacher in 2010, Flask gained popularity thanks to the philosophy “do one thing, and do it well”. Unlike heavier frameworks, Flask provides only the essential basics, allowing developers to choose their own components for each project.

Main features of Flask

Minimalist and extensible approach

Flask follows the micro‑framework principle, offering core functionality and allowing extensions via plugins and add‑ons.

Built‑in routing and request handling

The framework provides an intuitive routing system with support for various HTTP methods and URL parameters.

Jinja2 template support

Integration with the powerful Jinja2 templating engine enables convenient work with HTML templates and dynamic content.

Ability to create REST APIs

Flask is well‑suited for building RESTful APIs thanks to JSON response support and flexible HTTP method handling.

Extension support

A rich ecosystem of extensions lets you add functionality for databases, authentication, forms, and much more.

Compatibility with Python 3.7+

Flask supports modern versions of Python and follows best development practices.

Installation and setup

Installation via pip

pip install flask

Verify installation

python -m flask --version

Create app.py and run

export FLASK_APP=app.py
flask run

For Windows:

set FLASK_APP=app.py
flask run

Creating the first application

Simple example app.py

from flask import Flask

app = Flask(__name__)

@app.route("/")
def home():
    return "Welcome to Flask!"

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

Running the application

flask run

The application will be available at http://localhost:5000/

Routing and URLs

Basic routing

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

Typed routes

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

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

Supported parameter types

  • string – strings (default)
  • int – integers
  • float – floating‑point numbers
  • path – strings containing “/”
  • uuid – UUID strings

Working with HTTP methods

Handling different methods

@app.route("/data", methods=["GET", "POST", "PUT", "DELETE"])
def handle_data():
    if request.method == "POST":
        return "Data created"
    elif request.method == "PUT":
        return "Data updated"
    elif request.method == "DELETE":
        return "Data deleted"
    return "Data retrieved"

Working with Jinja2 templates

Creating templates

Create a templates folder and an index.html file:

<!-- templates/index.html -->
<!DOCTYPE html>
<html>
<head>
    <title>{{ title }}</title>
</head>
<body>
    <h1>Hello, {{ name }}!</h1>
    <p>Today is {{ date.strftime('%d.%m.%Y') }}</p>
</body>
</html>

Using it in the app

from flask import render_template
from datetime import datetime

@app.route("/hello/<name>")
def hello(name):
    return render_template("index.html",
                         name=name,
                         title="Greeting",
                         date=datetime.now())

Template inheritance

Base template base.html:

<!-- templates/base.html -->
<!DOCTYPE html>
<html>
<head>
    <title>{% block title %}My Site{% endblock %}</title>
</head>
<body>
    <nav>
        <ul>
            <li><a href="/">Home</a></li>
            <li><a href="/about">About</a></li>
        </ul>
    </nav>
    
    <main>
        {% block content %}{% endblock %}
    </main>
</body>
</html>

Child template:

<!-- templates/home.html -->
{% extends "base.html" %}

{% block title %}Home – My Site{% endblock %}

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

Form handling and POST/GET methods

Simple form

from flask import request

@app.route("/form", methods=["GET", "POST"])
def form():
    if request.method == "POST":
        username = request.form["username"]
        email = request.form["email"]
        return f"Hello, {username}! Email: {email}"
    
    return '''
    <form method="post">
        <input name="username" placeholder="Name" required>
        <input name="email" type="email" placeholder="Email" required>
        <input type="submit" value="Submit">
    </form>
    '''

File handling

from werkzeug.utils import secure_filename
import os

@app.route("/upload", methods=["GET", "POST"])
def upload_file():
    if request.method == "POST":
        if 'file' not in request.files:
            return "No file selected"
        
        file = request.files['file']
        if file.filename == '':
            return "No file selected"
        
        if file:
            filename = secure_filename(file.filename)
            file.save(os.path.join('uploads', filename))
            return f"File {filename} uploaded successfully"
    
    return '''
    <form method="post" enctype="multipart/form-data">
        <input type="file" name="file">
        <input type="submit" value="Upload">
    </form>
    '''

Working with databases

Using SQLAlchemy

pip install flask-sqlalchemy
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(20), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)
    password_hash = db.Column(db.String(60), nullable=False)
    posts = db.relationship('Post', backref='author', lazy=True)
    
    def __repr__(self):
        return f"User('{self.username}', '{self.email}')"

class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(100), nullable=False)
    content = db.Column(db.Text, nullable=False)
    date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    
    def __repr__(self):
        return f"Post('{self.title}', '{self.date_posted}')"

Creating the database

@app.before_first_request
def create_tables():
    db.create_all()

Creating a REST API with Flask

Basic API

from flask import jsonify, request

@app.route("/api/users", methods=["GET"])
def get_users():
    users = User.query.all()
    return jsonify([{
        'id': user.id,
        'username': user.username,
        'email': user.email
    } for user in users])

@app.route("/api/users", methods=["POST"])
def create_user():
    data = request.get_json()
    
    if not data or 'username' not in data or 'email' not in data:
        return jsonify({'error': 'Insufficient data'}), 400
    
    user = User(
        username=data['username'],
        email=data['email'],
        password_hash='hashed_password'  # In a real app, hash the password
    )
    
    db.session.add(user)
    db.session.commit()
    
    return jsonify({
        'message': 'User created',
        'user': {
            'id': user.id,
            'username': user.username,
            'email': user.email
        }
    }), 201

Using Flask-RESTful

pip install flask-restful
from flask_restful import Api, Resource

api = Api(app)

class UserListAPI(Resource):
    def get(self):
        users = User.query.all()
        return [{'id': u.id, 'username': u.username} for u in users]
    
    def post(self):
        data = request.get_json()
        user = User(username=data['username'], email=data['email'])
        db.session.add(user)
        db.session.commit()
        return {'message': 'User created'}, 201

api.add_resource(UserListAPI, '/api/users')

Working with sessions and cookies

Session configuration

from flask import session

app.secret_key = 'your-secret-key-here'  # Use os.urandom(24) in production

@app.route("/login", methods=["GET", "POST"])
def login():
    if request.method == "POST":
        username = request.form["username"]
        password = request.form["password"]
        
        # Simplified user check
        user = User.query.filter_by(username=username).first()
        if user and check_password_hash(user.password_hash, password):
            session["user_id"] = user.id
            session["username"] = user.username
            return redirect(url_for("dashboard"))
        else:
            return "Invalid login credentials"
    
    return '''
    <form method="post">
        <input name="username" placeholder="Username" required>
        <input name="password" type="password" placeholder="Password" required>
        <input type="submit" value="Log In">
    </form>
    '''

@app.route("/logout")
def logout():
    session.pop("user_id", None)
    session.pop("username", None)
    return redirect(url_for("home"))

Cookie handling

from flask import make_response

@app.route("/set_cookie")
def set_cookie():
    response = make_response("Cookie set")
    response.set_cookie("username", "john_doe", max_age=60*60*24)  # 24 hours
    return response

@app.route("/get_cookie")
def get_cookie():
    username = request.cookies.get("username", "Guest")
    return f"Hello, {username}!"

Error handling and logging

Error handling

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

@app.errorhandler(500)
def internal_error(error):
    db.session.rollback()
    return render_template("500.html"), 500

@app.errorhandler(403)
def forbidden(error):
    return render_template("403.html"), 403

Logging configuration

import logging
from logging.handlers import RotatingFileHandler

if not app.debug:
    if not os.path.exists('logs'):
        os.mkdir('logs')
    
    file_handler = RotatingFileHandler('logs/app.log', maxBytes=10240, backupCount=10)
    file_handler.setFormatter(logging.Formatter(
        '%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'
    ))
    file_handler.setLevel(logging.INFO)
    app.logger.addHandler(file_handler)
    app.logger.setLevel(logging.INFO)
    app.logger.info('Flask application started')

Integrating Flask extensions

Popular extensions

Flask‑WTF – forms and CSRF protection:

pip install flask-wtf

Flask‑Login – authentication system:

pip install flask-login

Flask‑Migrate – database migrations:

pip install flask-migrate

Flask‑Mail – email sending:

pip install flask-mail

Example using Flask‑WTF

from flask_wtf import FlaskForm
from wtforms import StringField, TextAreaField, SubmitField
from wtforms.validators import DataRequired, Email, Length

class ContactForm(FlaskForm):
    name = StringField('Name', validators=[DataRequired(), Length(min=2, max=50)])
    email = StringField('Email', validators=[DataRequired(), Email()])
    message = TextAreaField('Message', validators=[DataRequired(), Length(min=10)])
    submit = SubmitField('Send')

@app.route("/contact", methods=["GET", "POST"])
def contact():
    form = ContactForm()
    if form.validate_on_submit():
        # Process the form
        return redirect(url_for("thank_you"))
    return render_template("contact.html", form=form)

Organizing a large‑scale project

Recommended structure

project/
├── app/
│   ├── __init__.py
│   ├── models.py
│   ├── routes.py
│   ├── forms.py
│   └── utils.py
├── templates/
│   ├── base.html
│   ├── index.html
│   └── errors/
│       ├── 404.html
│       └── 500.html
├── static/
│   ├── css/
│   ├── js/
│   └── images/
├── migrations/
├── tests/
├── config.py
├── requirements.txt
└── run.py

Using Blueprint

# app/main.py
from flask import Blueprint

main = Blueprint('main', __name__)

@main.route('/')
def index():
    return render_template('index.html')

@main.route('/about')
def about():
    return render_template('about.html')
# app/__init__.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

def create_app():
    app = Flask(__name__)
    app.config.from_object('config')
    
    db.init_app(app)
    
    from app.main import main as main_blueprint
    app.register_blueprint(main_blueprint)
    
    return app

Testing Flask applications

Basic tests

import pytest
from app import create_app, db

@pytest.fixture
def app():
    app = create_app()
    app.config['TESTING'] = True
    app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:'
    
    with app.app_context():
        db.create_all()
        yield app
        db.drop_all()

@pytest.fixture
def client(app):
    return app.test_client()

def test_home_page(client):
    response = client.get('/')
    assert response.status_code == 200
    assert b'Welcome' in response.data

def test_login_post(client):
    response = client.post('/login', data={
        'username': 'testuser',
        'password': 'testpass'
    })
    assert response.status_code == 302  # Redirect after successful login

API testing

def test_api_users_get(client):
    response = client.get('/api/users')
    assert response.status_code == 200
    assert response.content_type == 'application/json'

def test_api_users_post(client):
    response = client.post('/api/users', json={
        'username': 'newuser',
        'email': 'newuser@example.com'
    })
    assert response.status_code == 201
    data = response.get_json()
    assert data['message'] == 'User created'

Deploying Flask applications

Using Gunicorn

pip install gunicorn
gunicorn -w 4 -b 127.0.0.1:8000 app:app

Docker container

FROM python:3.9-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install -r requirements.txt

COPY . .

EXPOSE 5000

CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:5000", "app:app"]

Production configuration

# config.py
import os

class Config:
    SECRET_KEY = os.environ.get('SECRET_KEY') or 'dev-secret-key'
    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or 'sqlite:///app.db'
    SQLALCHEMY_TRACK_MODIFICATIONS = False

class DevelopmentConfig(Config):
    DEBUG = True

class ProductionConfig(Config):
    DEBUG = False

config = {
    'development': DevelopmentConfig,
    'production': ProductionConfig,
    'default': DevelopmentConfig
}

Table of core Flask methods and functions

Component Description Example usage
Flask(__name__) Creates a Flask application instance app = Flask(__name__)
@app.route() Decorator for routing @app.route('/users')
render_template() Renders an HTML template render_template('index.html', data=data)
request.method HTTP request method if request.method == 'POST':
request.form Data from an HTML form username = request.form['username']
request.args Parameters from the URL page = request.args.get('page', 1)
request.json JSON request data data = request.json
request.files Uploaded files file = request.files['upload']
jsonify() Creates a JSON response return jsonify({'status': 'success'})
redirect() HTTP redirect return redirect(url_for('home'))
url_for() Generates a URL by endpoint name url_for('user_profile', id=1)
session Session handling session['user_id'] = user.id
make_response() Creates a response object resp = make_response('Hello')
abort() Raises an HTTP error abort(404)
flash() Messages for the user flash('Saved successfully')
get_flashed_messages() Retrieves flashed messages messages = get_flashed_messages()
@app.before_request Executes before each request @app.before_request
@app.after_request Executes after each request @app.after_request
@app.errorhandler() Error handling @app.errorhandler(404)
Blueprint() Creates an application module bp = Blueprint('main', __name__)
app.register_blueprint() Registers a Blueprint app.register_blueprint(bp)
current_app Current application context current_app.config['DEBUG']
g Global request context object g.user = current_user

Practical Flask use cases

Creating APIs for mobile applications

Flask is ideal for building RESTful APIs that serve mobile apps. Its lightweight nature and flexibility enable rapid development and scaling of API services.

Admin panels and CRM systems

By combining Flask with extensions like Flask‑Admin and Flask‑Login, you can build powerful admin dashboards and CRM solutions.

Back‑ends for chat bots and Telegram bots

Flask can serve as a webhook server to process messages from various messengers and social networks.

Real‑time monitoring and analytics

With WebSocket support via Flask‑SocketIO, you can create monitoring systems with live data updates.

Prototyping ML/AI models

Flask lets you quickly build web interfaces for machine learning and AI models, exposing them through REST APIs.

Security in Flask

CSRF protection

from flask_wtf.csrf import CSRFProtect

csrf = CSRFProtect(app)

Password hashing

from werkzeug.security import generate_password_hash, check_password_hash

password_hash = generate_password_hash('user_password')
is_valid = check_password_hash(password_hash, 'user_password')

Data validation

from wtforms.validators import DataRequired, Length, Email, ValidationError

def validate_username(self, username):
    user = User.query.filter_by(username=username.data).first()
    if user:
        raise ValidationError('Username is already taken')

Performance optimization

Caching

from flask_caching import Cache

cache = Cache(app)

@app.route('/expensive_operation')
@cache.cached(timeout=300)  # 5 minutes
def expensive_operation():
    # Long‑running operation
    return result

Pagination

@app.route('/posts')
def posts():
    page = request.args.get('page', 1, type=int)
    posts = Post.query.paginate(
        page=page,
        per_page=10,
        error_out=False
    )
    return render_template('posts.html', posts=posts)

Frequently asked questions

What is Flask and what is it used for?

Flask is a lightweight Python web framework for building web applications, REST APIs, and web services. It is great for prototyping, creating micro‑services, and developing both small and large web applications.

Does Flask support databases?

Yes, Flask works with various databases through extensions. The most popular is Flask‑SQLAlchemy, which integrates SQLAlchemy ORM and supports SQLite, PostgreSQL, MySQL, and others.

Is Flask an asynchronous framework?

Flask supports async functions starting with version 2.0, but it is not a fully asynchronous framework. For full async development, consider FastAPI or Quart.

Can Flask be used for large projects?

Yes, Flask can power large projects when architected properly. Key principles include using Blueprints for modularity, organizing code wisely, applying design patterns, and leveraging appropriate extensions.

How does Flask differ from Django?

Flask is a micro‑framework with minimal structure, providing only core components. Django is a full‑featured framework with many built‑in features (ORM, admin panel, authentication system). Flask offers more flexibility; Django offers more out‑of‑the‑box functionality.

How to ensure Flask application security?

Key security measures: use CSRF protection, hash passwords, validate user input, enforce HTTPS, set proper security headers, and keep dependencies up to date.

Which Flask extensions are most useful?

Most useful extensions: Flask‑SQLAlchemy (database), Flask‑Login (authentication), Flask‑WTF (forms), Flask‑Migrate (migrations), Flask‑Mail (email), Flask‑CORS (CORS), Flask‑Caching (caching).

How to deploy a Flask app in production?

For production, use a WSGI server (Gunicorn, uWSGI) behind a reverse proxy (Nginx). Containerization with Docker and cloud platforms (Heroku, AWS, Google Cloud) are also common options.

Conclusion

Flask is a powerful and flexible tool for developing Python web applications. Its philosophy of minimalism and extensibility makes it an ideal choice for a wide range of tasks—from simple prototypes to complex enterprise systems.

Key advantages of Flask:

  • Ease of learning and use
  • Flexibility and extensibility
  • Rich ecosystem of extensions
  • Active developer community
  • Excellent documentation
  • Compatibility with modern technologies

Thanks to these qualities, Flask remains one of the most popular Python web frameworks and continues to evolve, adapting to modern web development requirements. Whether you are a beginner or an experienced professional, Flask provides all the tools needed to build high‑quality web applications.

News