Kurs Python · Moduł 5: Flask i aplikacje webowe
Flask - mikroframework webowy
W tej lekcji11
Witaj z powrotem! Darwin tutaj, gotowy pokazać Ci Flask - najpopularniejszy mikroframework webowy w Pythonie!
W poprzedniej lekcji poznałeś/aś podstawy frontendu (HTML, CSS, JavaScript). Teraz połączymy to z Pythonem używając Flask!
Analogia Safari: Flask to jak mobilne centrum badawcze - lekkie, elastyczne, możesz je łatwo przenieść w dowolne miejsce i szybko zacząć obserwacje! Nie potrzebujesz ogromnego laboratorium (Django), aby rozpocząć badania.
Czym jest Flask?
Flask to mikroframework webowy napisany w Pythonie przez Armina Ronachera w 2010 roku.
Mikroframework = minimalistyczny framework z podstawowymi funkcjami, który możesz rozbudować wtyczkami.
Flask vs Django
| Flask | Django |
|---|---|
| Mikroframework - minimalistyczny | Full-stack framework - wszystko w jednym |
| Elastyczny, modułowy | Opinionated, konwencje |
| Świetny do małych/średnich projektów | Świetny do dużych projektów |
| Musisz sam wybrać komponenty | Wszystko out-of-the-box |
| ~10 linii dla Hello World | ~50 linii dla Hello World |
| Świetny do nauki! | Bardziej skomplikowany |
Analogia: Flask to namiot badawczy (szybkie ustawienie), Django to pełne laboratorium (długa konfiguracja, ale wszystkie narzędzia).
Po co używać Flask?
Prosty - minimalna krzywa uczenia Elastyczny - sam wybierasz komponenty Lekki - mała aplikacja, szybki start Pythonowy - czysty, czytelny kod Świetna dokumentacja - łatwo się uczyć Duża społeczność - mnóstwo wtyczek
Przykłady użycia Flask:
- Prototypy i MVP
- Dashboardy i panele admina
- API dla aplikacji mobilnych
- Wizualizacje danych
- Projekty edukacyjne
Instalacja Flask
Flask instalujemy przez pip jak każdy pakiet Pythona.
Krok 1: Stwórz wirtualne środowisko
Zawsze używaj wirtualnego środowiska dla projektów Pythona!
1# Stwórz folder projektu
2mkdir safari_web
3cd safari_web
4
5# Stwórz wirtualne środowisko
6python -m venv venv
7
8# Aktywuj środowisko
9# Windows:
10venv\Scripts\activate
11# Mac/Linux:
12source venv/bin/activateAnalogia: Wirtualne środowisko to jak odseparowana zagroda dla Twojego projektu - biblioteki z jednego projektu nie będą kolidować z innymi!
Krok 2: Zainstaluj Flask
1# Zainstaluj Flask
2pip install Flask
3
4# Sprawdź wersję
5flask --version
6# Output: Python 3.11.0
7# Flask 3.0.0
8# Werkzeug 3.0.0Flask automatycznie instaluje:
- Werkzeug - WSGI utility library (routing, debugging)
- Jinja2 - template engine (dynamiczny HTML)
- MarkupSafe - bezpieczne renderowanie HTML
- ItsDangerous - bezpieczne podpisywanie danych
- Click - CLI framework
Krok 3: Stwórz plik requirements.txt
1# Zapisz zależności
2pip freeze > requirements.txt
3
4# Zawartość requirements.txt:
5Flask==3.0.0
6Werkzeug==3.0.0
7Jinja2==3.1.2
8...Po co? Inni developerzy mogą zainstalować te same wersje:
1pip install -r requirements.txtPierwsza aplikacja Flask - Hello World
Czas na pierwszy program Flask! Stworzymy stronę wyświetlającą "Hello Safari!"
Krok 1: Stwórz plik app.py
1# app.py
2from flask import Flask
3
4# Stwórz instancję aplikacji Flask
5app = Flask(__name__)
6
7# Zdefiniuj route (adres URL)
8@app.route('/')
9def hello():
10 return "Hello Safari!"
11
12# Uruchom serwer developerski
13if __name__ == '__main__':
14 app.run(debug=True)Co się dzieje?
Flask(__name__)- tworzy instancję aplikacji__name__to nazwa modułu (Flask używa tego do lokalizacji zasobów)
@app.route('/')- dekorator definiujący route (ścieżkę URL)/= strona główna (home page)- Gdy użytkownik wejdzie na
http://localhost:5000/, wykona się funkcjahello()
def hello()- view function (funkcja widoku)- Zwraca treść, która zostanie wyświetlona użytkownikowi
app.run(debug=True)- uruchamia serwer deweloperskidebug=Truewłącza tryb debugowania (auto-reload, szczegółowe błędy)
Krok 2: Uruchom aplikację
1python app.pyOutput:
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!Krok 3: Otwórz w przeglądarce
Przejdź do: http://localhost:5000/
Zobaczysz: Hello Safari!
Gratulacje! Właśnie stworzyłeś/aś pierwszą aplikację Flask!
Anatomia aplikacji Flask
Przeanalizujmy dokładniej, jak działa Flask.
1. Instancja aplikacji
1from flask import Flask
2
3app = Flask(__name__)Flask(__name__) tworzy obiekt aplikacji:
__name__= nazwa modułu (np.'__main__'lub'app')- Flask używa tego do lokalizacji templates, static files
2. Routes (ścieżki URL)
Route = mapowanie URL → funkcja
1@app.route('/species')
2def list_species():
3 return "Lista wszystkich gatunków"
4
5@app.route('/species/lion')
6def show_lion():
7 return "Szczegóły lwa"Jak to działa?
- Użytkownik wchodzi na
/species→ wykonuje sięlist_species() - Użytkownik wchodzi na
/species/lion→ wykonuje sięshow_lion()
Analogia: Route to jak szlak safari - każdy szlak prowadzi do innego siedliska (view function)!
3. View functions (funkcje widoku)
View function = funkcja zwracająca odpowiedź HTTP
1@app.route('/')
2def home():
3 return "<h1>Safari Database</h1><p>Witaj w systemie!</p>"Co możesz zwrócić?
- String - zostanie przekonwertowany na HTML
- HTML - renderowany w przeglądarce
- JSON - dla API (
jsonify()) - Template - dynamiczny HTML z Jinja2
4. Uruchomienie serwera
1if __name__ == '__main__':
2 app.run(debug=True)Parametry app.run():
debug=True- tryb debugowania (auto-reload, debugger)host='0.0.0.0'- dostępny z innych urządzeńport=5000- numer portu (domyślnie 5000)
WAŻNE: NIGDY nie używaj debug=True w produkcji!
Safari Database - pierwsza aplikacja
Stworzymy prostą aplikację Safari Database z kilkoma route'ami!
app.py - pełna aplikacja
1# app.py
2from flask import Flask
3
4app = Flask(__name__)
5
6# Dane testowe
7species = [
8 {"id": 1, "name": "Lew", "scientific_name": "Panthera leo", "population": 120},
9 {"id": 2, "name": "Słoń afrykański", "scientific_name": "Loxodonta africana", "population": 450},
10 {"id": 3, "name": "Gepard", "scientific_name": "Acinonyx jubatus", "population": 7100},
11]
12
13# Route 1: Strona główna
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>System zarządzania danymi o gatunkach afrykańskich</p>
43
44 <nav>
45 <a href="/">Strona główna</a>
46 <a href="/species">Lista gatunków</a>
47 <a href="/about">O systemie</a>
48 </nav>
49
50 <h2>Witaj w Safari Database!</h2>
51 <p>Baza danych zawiera <strong>{} gatunków</strong> afrykańskich.</p>
52 <p><a href="/species">Zobacz pełną listę gatunków →</a></p>
53 </body>
54 </html>
55 """.format(len(species))
56
57 return html
58
59# Route 2: Lista gatunków
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>Nazwa naukowa:</strong> {spec['scientific_name']}</p>
68 <p><strong>Populacja:</strong> {spec['population']} osobników</p>
69 <a href="/species/{spec['id']}">Zobacz szczegóły →</a>
70 </div>
71 """
72
73 html = f"""
74 <!DOCTYPE html>
75 <html>
76 <head>
77 <title>Lista gatunków - 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>Lista gatunków</h1>
99
100 <nav>
101 <a href="/">Strona główna</a>
102 <a href="/species">Lista gatunków</a>
103 <a href="/about">O systemie</a>
104 </nav>
105
106 <p>Łącznie: <strong>{len(species)} gatunków</strong></p>
107
108 {species_html}
109
110 <p><a href="/">← Powrót do strony głównej</a></p>
111 </body>
112 </html>
113 """
114
115 return html
116
117# Route 3: Szczegóły gatunku (dynamiczny URL)
118@app.route('/species/<int:species_id>')
119def show_species(species_id):
120 # Znajdź gatunek po 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 - Gatunek nie znaleziony</h1><a href='/species'>Powrót do listy</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>Nazwa naukowa:</strong> <em>{spec['scientific_name']}</em></p>
154 <p><strong>Populacja:</strong> {spec['population']} osobników</p>
155 <p><strong>ID w systemie:</strong> {spec['id']}</p>
156 </div>
157
158 <p style="margin-top: 20px;">
159 <a href="/species">← Powrót do listy gatunków</a> |
160 <a href="/">← Strona główna</a>
161 </p>
162 </body>
163 </html>
164 """
165
166 return html
167
168# Route 4: O systemie
169@app.route('/about')
170def about():
171 html = """
172 <!DOCTYPE html>
173 <html>
174 <head>
175 <title>O systemie - 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>O Safari Database</h1>
189
190 <p><strong>Safari Database</strong> to system zarządzania danymi o gatunkach afrykańskich.</p>
191
192 <h2>Technologie:</h2>
193 <ul>
194 <li>Flask 3.0 - mikroframework webowy</li>
195 <li>Python 3.11 - język programowania</li>
196 <li>HTML/CSS - frontend</li>
197 </ul>
198
199 <h2>Funkcje:</h2>
200 <ul>
201 <li>Przeglądanie listy gatunków</li>
202 <li>Szczegóły każdego gatunku</li>
203 <li>Statystyki populacji</li>
204 </ul>
205
206 <p><a href="/">← Powrót do strony głównej</a></p>
207 </body>
208 </html>
209 """
210
211 return html
212
213# Uruchom serwer deweloperski
214if __name__ == '__main__':
215 print("Safari Database startuje...")
216 print("Serwer dostępny pod adresem: http://localhost:5000/")
217 app.run(debug=True)Testowanie aplikacji
1python app.pyOtwórz w przeglądarce:
- http://localhost:5000/ - strona główna
- http://localhost:5000/species - lista gatunków
- http://localhost:5000/species/1 - szczegóły lwa
- http://localhost:5000/species/2 - szczegóły słonia
- http://localhost:5000/about - o systemie
Sprawdź też błędy:
- http://localhost:5000/species/999 - gatunek nie istnieje (404)
Dynamiczne URL - parametry
Flask pozwala na dynamiczne URL z parametrami:
1# Podstawowy parametr (string)
2@app.route('/user/<username>')
3def show_user(username):
4 return f"Użytkownik: {username}"
5
6# Parametr typu int
7@app.route('/species/<int:species_id>')
8def show_species(species_id):
9 return f"Gatunek ID: {species_id}"
10
11# Parametr typu float
12@app.route('/price/<float:price>')
13def show_price(price):
14 return f"Cena: {price:.2f} zł"
15
16# Parametr path (może zawierać /)
17@app.route('/file/<path:filepath>')
18def show_file(filepath):
19 return f"Plik: {filepath}"Typy konwerterów:
string- akceptuje tekst bez slasha (domyślny)int- akceptuje liczby całkowitefloat- akceptuje liczby zmiennoprzecinkowepath- jak string, ale akceptuje slasheuuid- akceptuje UUID strings
Przykłady URL:
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 i POST
Flask domyślnie obsługuje tylko GET requests. Możesz dodać inne metody:
1from flask import request
2
3# Tylko GET (domyślnie)
4@app.route('/species')
5def list_species():
6 return "Lista gatunków (GET)"
7
8# GET i POST
9@app.route('/species', methods=['GET', 'POST'])
10def species():
11 if request.method == 'POST':
12 # Obsługa formularza
13 name = request.form['name']
14 return f"Dodano gatunek: {name}"
15 else:
16 # Wyświetl formularz
17 return """
18 <form method="POST">
19 <input type="text" name="name" placeholder="Nazwa gatunku">
20 <button type="submit">Dodaj</button>
21 </form>
22 """
23
24# Tylko POST
25@app.route('/api/species', methods=['POST'])
26def create_species():
27 return "Utworzono gatunek (POST only)"Metody HTTP:
- GET - pobierz dane (domyślne, bezpieczne)
- POST - wyślij dane (formularze, tworzenie)
- PUT - aktualizuj dane (pełna aktualizacja)
- PATCH - aktualizuj częściowo
- DELETE - usuń dane
Debugowanie i Auto-reload
Debug mode (debug=True) włącza:
1. Auto-reload
Serwer automatycznie restartuje się po zmianie kodu!
1app.run(debug=True)Testuj:
- Uruchom
python app.py - Zmień coś w kodzie (np. tekst w route)
- Zapisz plik
- Flask automatycznie przeładuje aplikację!
2. Interaktywny debugger
Gdy wystąpi błąd, Flask pokazuje interaktywny debugger w przeglądarce:
1@app.route('/error')
2def error():
3 result = 10 / 0 # Błąd: dzielenie przez zero!
4 return "This won't be reached"Wejdź na /error → zobaczysz szczegółowy traceback z możliwością inspekcji zmiennych!
3. Szczegółowe komunikaty błędów
Flask pokazuje dokładne informacje o błędach zamiast ogólnego "500 Internal Server Error".
WAŻNE: NIGDY nie używaj debug=True w produkcji - pokazuje kod źródłowy i pozwala wykonywać kod!
Flask CLI - alternatywny sposób uruchamiania
Zamiast python app.py możesz użyć Flask CLI:
1# Ustaw zmienną środowiskową
2export FLASK_APP=app.py
3export FLASK_DEBUG=1 # Włącz debug mode
4
5# Uruchom serwer
6flask run
7
8# Uruchom na innym porcie
9flask run --port 8000
10
11# Dostępny z innych urządzeń
12flask run --host=0.0.0.0Windows (PowerShell):
1$env:FLASK_APP = "app.py"
2$env:FLASK_DEBUG = "1"
3flask runStruktura projektu Flask
Prosty projekt Flask może wyglądać tak:
1safari_web/
2│
3├── venv/ # Wirtualne środowisko (nie commituj do git!)
4│
5├── app.py # Główna aplikacja
6│
7├── requirements.txt # Zależności (pip freeze)
8│
9├── static/ # Pliki statyczne (CSS, JS, obrazy)
10│ ├── css/
11│ │ └── style.css
12│ ├── js/
13│ │ └── script.js
14│ └── images/
15│ └── logo.png
16│
17├── templates/ # Szablony HTML (Jinja2)
18│ ├── base.html
19│ ├── home.html
20│ └── species.html
21│
22└── .gitignore # Ignoruj venv/, __pycache__/, etc.W następnej lekcji nauczymy się używać templates zamiast hardcoded HTML strings!
Podsumowanie
W tej lekcji nauczyłeś/aś się:
- Czym jest Flask i po co go używać
- Instalacja Flask (
pip install Flask) - Pierwszy program Flask (Hello World)
- Anatomia aplikacji Flask (app, routes, view functions)
- Tworzenie wielu routes
- Dynamiczne URL z parametrami
- Debug mode i auto-reload
- Struktura projektu Flask
Analogia Safari finalna: Flask to mobilne centrum badawcze - lekkie, szybko się ustawia, możesz zacząć obserwacje w kilka minut! Nie potrzebujesz ogromnego laboratorium (Django), żeby rozpocząć badania Safari!
Kod aplikacji Safari Database
Stworzyłeś/aś funkcjonującą aplikację webową z:
- 4 routes (home, species list, species details, about)
- Dynamiczne URL (
/species/<int:species_id>) - HTML + inline CSS
- Dane testowe (lista gatunków)
Następna lekcja: Darwin pokaże Ci routing i view functions - zaawansowane techniki tworzenia routes, redirects, error handlers!
Widzisz błąd w tej lekcji?
Sprawdź się
Odpowiedz na pytania z tej lekcji. Wybierz odpowiedź, a od razu zobaczysz, czy jest poprawna.
1. Jak najlepiej opisać Flask?
2. Jak zainstalować Flask za pomocą pip?
To 2 z 3 pytań do tej lekcji. Pozostałe rozwiążesz w grze.
Zadania praktyczne w grze
- Układanie w pionie
Ułóż kod minimalnej aplikacji Flask w poprawnej kolejności:
- Klikanie w kolejności
Jak utworzyć instancję aplikacji Flask?
- Edytor kodu
Napisz aplikację Flask z endpointem '/' który zwraca 'Witaj w Safari!'