Flask to lekki i elastyczny mikroframework dla Pythona, który od ponad dekady pozostaje jednym z najpopularniejszych wyborów do budowy aplikacji webowych. Stworzony przez Armina Ronachera w 2010 roku, Flask łączy prostotę z potężnymi możliwościami rozszerzeń. W tym artykule poznasz fundamenty frameworka i zbudujesz swoją pierwszą aplikację webową.
🎯 Czego się nauczysz:
- Instalacja i konfiguracja Flask
- Podstawowe koncepcje: routing, widoki, szablony
- Obsługa formularzy i danych
- Praca z bazą danych (SQLAlchemy)
- Sesje i ciasteczka
- Autentykacja użytkowników
- Struktura projektu i best practices
- Deployment aplikacji
TL;DR — Szybkie podsumowanie
| Aspekt | Django | Flask |
|---|---|---|
| Rozmiar | ⚠️ Duży (batteries included) | ✅ Minimalny (mikroframework) |
| Elastyczność | ⚠️ Sztywna struktura | ✅ Pełna swoboda |
| Admin panel | ✅ Built-in | ❌ Brak (trzeba dodać) |
| Nauka | ⚠️ Więcej do przyswojenia | ✅ Prostszy start |
| Użycie | Duże aplikacje | Małe/średnie projekty, API |
🐍 Czym jest Flask?
Flask nazywany jest “mikroframeworkiem” nie dlatego, że brakuje mu funkcjonalności, ale dlatego, że jego rdzeń jest minimalistyczny. W przeciwieństwie do Django, Flask nie narzuca struktury projektu – daje Ci swobodę decydowania, jak zorganizować kod.
Kluczowe cechy
- Lekki rdzeń – minimalistyczny kod źródłowy, szybkie uruchomienie
- Elaboratory – bogaty ekosystem rozszerzeń: SQLAlchemy, Flask-Login, Flask-WTF
- Prosty routing – intuicyjny system dekoratorów do mapowania URL-i
- Jinja2 Templates – potężny silnik szablonów z dziedziczeniem i makrami
⚙️ Instalacja
# Tworzenie wirtualnego środowiska
python -m venv venv
# Aktywacja (Windows)
venv\Scripts\activate
# Aktywacja (Linux/Mac)
source venv/bin/activate
# Instalacja Flask
pip install flask
# Instalacja z dodatkowymi pakietami
pip install flask flask-sqlalchemy flask-wtf flask-login
# Sprawdzenie wersji
python -c "import flask; print(flask.__version__)"
🚀 Pierwsza aplikacja
Najprostsza aplikacja Flask składa się z zaledwie kilku linii kodu:
from flask import Flask
# Inicjalizacja aplikacji
app = Flask(__name__)
# Definicja trasy
@app.route('/')
def hello():
return 'Witaj, świecie!'
# Uruchomienie serwera
if __name__ == '__main__':
app.run(debug=True)
Zapisz kod w pliku app.py i uruchom:
python app.py
Aplikacja będzie dostępna pod adresem http://127.0.0.1:5000.
🗺️ Routing i zmienne
Flask pozwala definiować dynamiczne trasy z parametrami:
from flask import Flask, abort
app = Flask(__name__)
# Statyczna trasa
@app.route('/about')
def about():
return 'O nas'
# Trasa z parametrem
@app.route('/user/<username>')
def show_user(username):
return f'Profil użytkownika: {username}'
# Parametr z typem
@app.route('/post/<int:post_id>')
def show_post(post_id):
return f'Post numer: {post_id}'
# Wiele metod HTTP
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
return 'Logowanie...'
else:
return 'Formularz logowania'
🎨 Szablony Jinja2
Flask używa silnika szablonów Jinja2. Szablony umieszczamy w folderze templates:
Szablon bazowy
<!DOCTYPE html>
<html>
<head>
<title>{% raw %}{{ title }}{% endraw %} - Moja Aplikacja</title>
<link rel="stylesheet" href="{% raw %}{{ url_for('static', filename='css/style.css') }}{% endraw %}">
</head>
<body>
<nav>
<a href="{% raw %}{{ url_for('index') }}{% endraw %}">Strona główna</a>
<a href="{% raw %}{{ url_for('about') }}{% endraw %}">O nas</a>
</nav>
{% raw %}{% block content %}{% endblock %}{% endraw %}
<footer>
<p>© 2026 Moja Aplikacja</p>
</footer>
</body>
</html>
Szablon rozszerzający
{% raw %}{% extends "base.html" %}{% endraw %}
{% raw %}{% block content %}{% endraw %}
<h1>Witaj, {% raw %}{{ username }}{% endraw %}!</h1>
{% raw %}{% if posts %}{% endraw %}
<ul>
{% raw %}{% for post in posts %}{% endraw %}
<li>
<h2>{% raw %}{{ post.title }}{% endraw %}</h2>
<p>{% raw %}{{ post.content | truncate(100) }}{% endraw %}</p>
</li>
{% raw %}{% endfor %}{% endraw %}
</ul>
{% raw %}{% else %}{% endraw %}
<p>Brak postów do wyświetlenia.</p>
{% raw %}{% endif %}{% endraw %}
{% raw %}{% endblock %}{% endraw %}
Renderowanie szablonu
from flask import render_template
@app.route('/')
def index():
posts = [
{'title': 'Pierwszy post', 'content': 'Treść pierwszego posta...'},
{'title': 'Drugi post', 'content': 'Treść drugiego posta...'}
]
return render_template('index.html',
title='Strona główna',
username='Jan',
posts=posts)
📝 Formularze i walidacja
Do obsługi formularzy najlepiej użyć rozszerzenia Flask-WTF:
pip install flask-wtf
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired, Email, Length
class LoginForm(FlaskForm):
email = StringField('Email', validators=[
DataRequired(),
Email()
])
password = PasswordField('Hasło', validators=[
DataRequired(),
Length(min=6, message='Hasło musi mieć min. 6 znaków')
])
submit = SubmitField('Zaloguj się')
from flask import Flask, render_template, redirect, flash
from forms import LoginForm
app = Flask(__name__)
app.config['SECRET_KEY'] = 'twoj-tajny-klucz'
@app.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
flash(f'Zalogowano jako {form.email.data}', 'success')
return redirect('/')
return render_template('login.html', form=form)
💾 Baza danych z SQLAlchemy
pip install flask-sqlalchemy
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
# Definicja modelu
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
created_at = db.Column(db.DateTime, server_default=db.func.now())
def __repr__(self):
return f'<User {self.username}>'
# Tworzenie tabel
with app.app_context():
db.create_all()
# CRUD operations
@app.route('/users')
def get_users():
users = User.query.all()
return {'users': [{'id': u.id, 'username': u.username} for u in users]}
@app.route('/users', methods=['POST'])
def create_user():
data = request.get_json()
user = User(username=data['username'], email=data['email'])
db.session.add(user)
db.session.commit()
return {'message': 'Użytkownik utworzony', 'id': user.id}, 201
🔐 Autentykacja z Flask-Login
pip install flask-login
from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required, current_user
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True)
email = db.Column(db.String(120), unique=True)
password_hash = db.Column(db.String(128))
def set_password(self, password):
self.password_hash = generate_password_hash(password)
def check_password(self, password):
return check_password_hash(self.password_hash, password)
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
@app.route('/login', methods=['POST'])
def login():
user = User.query.filter_by(username=request.form['username']).first()
if user and user.check_password(request.form['password']):
login_user(user, remember=True)
return redirect(url_for('dashboard'))
flash('Nieprawidłowe dane logowania')
return redirect(url_for('login'))
@app.route('/dashboard')
@login_required
def dashboard():
return f'Witaj, {current_user.username}!'
@app.route('/logout')
@login_required
def logout():
logout_user()
return redirect(url_for('index'))
📁 Struktura projektu
Dla większych aplikacji zalecana jest struktura typu “application factory”:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
db = SQLAlchemy()
login_manager = LoginManager()
def create_app(config_name='default'):
app = Flask(__name__)
app.config.from_object(f'config.{config_name}Config')
# Inicjalizacja rozszerzeń
db.init_app(app)
login_manager.init_app(app)
# Rejestracja blueprintów
from .routes.main import main_bp
from .routes.auth import auth_bp
app.register_blueprint(main_bp)
app.register_blueprint(auth_bp, url_prefix='/auth')
return app
🚀 Deployment
Do produkcji użyj WSGI servera, np. Gunicorn:
# Instalacja
pip install gunicorn
# Uruchomienie
gunicorn -w 4 -b 0.0.0.0:8000 "app:create_app()"
# Z plikiem konfiguracyjnym
gunicorn -c gunicorn.conf.py "app:create_app()"
bind = "0.0.0.0:8000"
workers = 4
worker_class = "sync"
worker_connections = 1000
timeout = 30
keepalive = 2
errorlog = "-"
accesslog = "-"
loglevel = "info"
debug=True w produkcji! Tryb debug ujawnia poufne informacje i pozwala na zdalne wykonywanie kodu.
📊 Podsumowanie
| Funkcja | Kod | Opis |
|---|---|---|
| Routing | @app.route(‘/path’) | Mapowanie URL na funkcję |
| Szablony | render_template() | Renderowanie HTML z Jinja2 |
| Formularze | FlaskForm | Walidacja i obsługa formularzy |
| Baza danych | SQLAlchemy | ORM do pracy z bazą |
| Sesje | session[‘key’] | Przechowywanie danych użytkownika |
| Autentykacja | Flask-Login | Zarządzanie logowaniem |
| Blueprints | Blueprint() | Organizacja kodu w moduły |
✅ Kiedy używać Flask?
✅ Idealne dla:
- Małych i średnich projektów
- API REST
- Mikroserwisów
- Szybkich prototypów
- Projektów wymagających elastyczności
- Nauki web developmentu
❌ Rozważ alternatywę gdy:
- Potrzebujesz wbudowanego admina (→ Django)
- Duży projekt z wieloma modułami
- Wymagasz ORM z migracjami out-of-the-box
- Chcesz mniej decyzji architektonicznych
- Projekt enterprise z rigidnymi wymaganiami
📚 Bibliografia
- Pallets Projects. (2026). Flask Documentation. flask.palletsprojects.com
- Pallets Projects. (2026). Flask GitHub Repository. github.com/pallets/flask
- Pallets Projects. (2026). Jinja2 Documentation. jinja.palletsprojects.com
- Flask-SQLAlchemy. (2026). Flask-SQLAlchemy Documentation. flask-sqlalchemy.palletsprojects.com
- Flask-Login. (2026). Flask-Login Documentation. flask-login.readthedocs.io