6.1. Quiz
Realizacja aplikacji internetowej Quiz w oparciu o framework Flask 3.1.x Na stronie wyświetlamy pytania, użytkownik zaznacza poprawne odpowiedzi, przesyła je na serwer i otrzymuje informację o wynikach.
6.1.1. Środowisko pracy
Do tworzenia aplikacji z użyciem Flaska możesz użyć dowolnych narzędzi, np. terminala i ulubionego edytora kodu. Sugerujemy jednak wykorzystanie środowiska PyCharm, ponieważ w dużym stopniu ułatwia pracę nad projektami w języku Python.
Przed rozpoczęciem pracy przygotuj w katalogu projekty_flask` wirtualne środowisko Pythona
i w aktywnym środowisku zainstaluj pakiet Flask:
(.venv) ~/projekty_flask$ pip install flask
6.1.2. Projekt i aplikacja
W katalogu projekty_flask` tworzymy nowy katalog aplikacji o nazwie quiz:
(.venv) ~/projekty_flask$ mkdir quiz
(.venv) ~/projekty_flask$ cd quiz
Utworzymy szkielet aplikacji Flask, co pozwoli na uruchomienie testowego serwera www.
W katalogu aplikacji quiz dodajemy plik o nazwie app.py i umieszczamy w nim poniższy kod.
1from flask import Flask
2
3app = Flask(__name__)
4
5@app.route('/')
6def index():
7 return 'Cześć, tu Python i Flask!'
8
9with app.app_context():
10 if __name__ == "__main__":
11 app.run(debug=True)
Serwer uruchamiamy jednym z poleceń w terminalu w katalogu projektu:
flask run --debug lub python3 app.py (py app.py w systemie Windows):
(.venv) ~/projekty_flask/quiz$ flask run --debug
Domyślnie serwer uruchamia się pod adresem http://127.0.0.1:5000.
Po otwarciu przeglądarki i wpisaniu tego adresu (można też kliknąć adres wyświetlony w terminalu
z wciśniętym klawiszem CTLR) zobaczymy napis zwrócony przez aplikację: „Cześć, tu Python i Flask!”.
Wskazówka
Działanie serwera zatrzymujemy w terminalu skrótem CTRL+C.
6.1.3. Strona główna
Nasza aplikacja zwraca użytkownikowi stronę główną za pomocą widoku index().
Jest to funkcja Pythona powiązana z określonym w dekoratorze route('/')
adresem / oznaczającym domyślny zasób serwera.
Widoki obsługują podstawowe żądania protokołu HTTP wysyłane przez przeglądarkę.
Informacja
Żądania typu GET występują wtedy, kiedy chcemy pobrać jakieś dane z serwera, np. stronę. Ewentualne dane przekazywane do serwera (np. parametry wyszukiwania) widoczne są w adresie URL, np.:
www.google.com/search?client=firefox-b-lm&channel=entpr&q=żądania+GET+i+POST
Żądanie typu POST służą natomiast do przesyłania na serwer danych niewidocznych w adresie URL,
które mają zazwyczaj zmieniać stan aplikacji, np. dodać lub zalogować użytkownika.
Do przesyłania danych metodą POST służą formularze.
W odpowiedzi na żądanie aplikacja może odsyłać różne dane, np. predefiniowany tekst, ale najczęściej będzie to strona HTML zawierająca różne w zależności od żądania informacje, np. formularz z pytaniami albo wyniki quizu.
Flask ułatwia tworzenie takich stron za pomocą tzw. szablonów (zob. szablon).
Szablony umieścimy w katalogu quiz/templates, kóry należy utworzyć:
(.venv) ~/projekty_flask/quiz$ mkdir templates
Następnie w utworzonym katalogu dodajemy plik index.html i umieszczamy w nim kod:
1<!-- projekty_flask/quiz/templates/index.html -->
2<html>
3 <head>
4 <title>{{ config.SITE_NAME }}</title>
5 </head>
6<body>
7 <h1>{{ config.SITE_NAME }}</h1>
8</body>
9</html>
W miejsce oznaczone tagiem {{ config.SITE_NAME }} wstawiona zostanie nazwa serwisu, którą zdefiniujemy
w ustawieniach aplikacji.
Uzupełniamy i zmieniamy kod w pliku app.py:
1from flask import Flask, render_template
2
3app = Flask(__name__)
4
5# konfiguracja aplikacji
6app.config.update(dict(
7 SECRET_KEY='bradzosekretnawartosc',
8 SITE_NAME='Quiz Python'
9))
10
11@app.route('/')
12def index():
13 # return 'Cześć, tu Python i Flask!'
14 return render_template('index.html')
15
16with app.app_context():
17 if __name__ == "__main__":
18 app.run(debug=True)
Konfiguracja aplikacji przechowywana jest w słowniku config, do którego dodajemy
sekretny klucz, wykorzystywany do obsługi sesji (zob sesja) oraz nazwę serwisu.
Do renderowania szablonu (zob: renderowanie szablonu) używamy
zaimportowanej na początku pliku funkcji render_template('index.html'), która jako argument przyjmuje
nazwę pliku szablonu.
Po otworzeniu strony głównej (http://127.0.0.1:5000) zobaczymy stronę:
6.1.4. Pytania i odpowiedzi
Dane aplikacji, a więc pytania i odpowiedzi, umieścimy w pliku app.py – to najprostsze
rozwiązanie, żeby nie wprowadzać na razie obsługi bazy danych.
Nowy kod wstawiamy po instrukcji app = Flask(__name__):
1from flask import Flask, render_template
2
3app = Flask(__name__)
4
5# konfiguracja aplikacji
6app.config.update(dict(
7 SECRET_KEY='bradzosekretnawartosc',
8 SITE_NAME='Quiz Python'
9))
10
11# lista pytań
12dane = [{
13 'pytanie': 'Stolica Hiszpani, to:', # pytanie
14 'odpowiedzi': ['Madryt', 'Warszawa', 'Barcelona'], # możliwe odpowiedzi
15 'odpok': 'Madryt'}, # poprawna odpowiedź
16 {
17 'pytanie': 'Objętość sześcianu o boku 6 cm, wynosi:',
18 'odpowiedzi': ['36', '216', '18'],
19 'odpok': '216'},
20 {
21 'pytanie': 'Symbol pierwiastka Helu, to:',
22 'odpowiedzi': ['Fe', 'H', 'He'],
23 'odpok': 'He'},
24]
25
26@app.route('/pytania')
27def pytania():
28 return render_template('pytania.html', pytania=dane)
29
30@app.route('/')
31def index():
32 # return 'Cześć, tu Python i Flask!'
33 return render_template('index.html')
34
35with app.app_context():
36 if __name__ == "__main__":
37 app.run(debug=True)
Źródłem danych dla naszej aplikacji będzie lista dane, która zawiera trzy słowniki.
W każdym słowniku umieszczamy treść pytania, możliwe odpowiedzi oraz odpowiedź poprawną.
Dalej definiujemy nowy adres URL /pytania, który będzie obsługiwany przez
funkcję pytania(). W funkcji zwracamy szablon pytania.html,
do którego przekazujemy listę dane w zmiennej pytania.
W katalogu templates tworzymy nowy plik pytania.html i wstawiamy
do niego poniższy kod:
1<!-- projekty_flask/quiz/templates/pytania.html -->
2<html>
3 <head>
4 <title>Quiz Python</title>
5 </head>
6 <body>
7 <h1>Quiz Python</h1>
8
9 <!-- wyświetlamy komunikaty z funkcji flash -->
10 <p>
11 {% for komunikat in get_flashed_messages() %}
12 {{ komunikat }}
13 {% endfor %}
14 </p>
15
16 <!-- formularz z quizem -->
17 <form method="POST" action="{{ url_for('pytania') }}">
18 <!-- przeglądamy listę pytań -->
19 {% for p in pytania %}
20 <p>
21 <!-- wyświetlamy treść pytania -->
22 {{ p.pytanie }}
23 <br>
24 <!-- zapamiętujemy numer pytania licząc od zera -->
25 {% set pnr = loop.index0 %}
26 <!-- przeglądamy odpowiedzi dla danego pytania -->
27 {% for o in p.odpowiedzi %}
28 <label>
29 <!-- odpowiedzi wyświetlamy jako pole typu radio -->
30 <input type="radio" value="{{ o }}" name="{{ pnr }}">
31 {{ o }}
32 </label>
33 <br>
34 {% endfor %}
35 </p>
36 {% endfor %}
37
38 <!-- przycisk wysyłający wypełniony formularz -->
39 <button type="submit">Sprawdź odpowiedzi</button>
40 </form>
41
42 <p>
43 <a href="{{ url_for('index') }}">Strona główna</a>
44 </p>
45
46 </body>
47</html>
W szablonie używamy specjalnych tagów:
{% instrukcja %}– tak wstawiamy instrukcje sterujące typufor,setczyif;{{ zmienna }}– tak wstawiamy wartości danych przekazanych do szablonu.
Pętla {% for komunikat in get_flashed_messages() %} odpowiada za wstawienie komunikatów,
które przygotujemy dla użytkownika w widoku pytania().
Znacznik <form> tworzy formularz, który wysyłany będzie na adres URL zdefiniowany w atrybucie action.
Adres ten generujemy przy użyciu funkcji url_for('pytania'). Jako argument przyjmuje ona nazwę widoku.
W formularzu wstawiamy pytania i możliwe odpowiedzi: z przekazanej do szablonu zmiennej pytania
odczytujemy w pętli {% for p in pytania %} kolejne słowniki. Dalej w znacznikach akapitu <p>
wyświetlamy treść pytania {{ p.pytanie }}, a w kolejnej pętli {% for o in p.odpowiedz %}
– odpowiedzi jako grupy opcji typu radio <input type="radio">.
Każda grupa odpowiedzi nazywana jest dla odróżnienia numerem pytania liczonym od 0.
Odpowiednią zmienną ustawiamy w instrukcji {% set pnr = loop.index0 %},
a używamy w postaci name="{{ pnr }}". Dzięki temu przyporządkujemy
przesłane odpowiedzi do kolejnych pytań podczas ich sprawdzania.
Na końcu w znaczniku <a> generujemy adres strony głównej za pomocą wspomnianej
funkcji url_for('index'), której argumentem jest nazwa widoku,
czyli funkcji w tym przypadku obsługującej adres domyślny.
Po uruchomieniu serwera i wpisaniu w przeglądarce adresu http://127.0.0.1:5000/pytania
powinniśmy zobaczyć:
6.1.5. Oceniamy odpowiedzi
Kod sprawdzający liczbę poprawnych odpowiedzi umieścimy w widoku pytania().
Na początku pliku app.py dodajemy potrzebne importy:
3from flask import request, redirect, url_for, flash
– i uzupełniamy kod funkcji pytania():
27@app.route('/pytania', methods=['GET', 'POST'])
28def pytania():
29 if request.method == 'POST':
30 punkty = 0
31 odpowiedzi = request.form
32
33 for pnr, odp in odpowiedzi.items():
34 if odp == dane[int(pnr)]['odpok']:
35 punkty += 1
36
37 flash('Liczba poprawnych odpowiedzi, to: {0}'.format(punkty))
38 return redirect(url_for('pytania'))
39 return render_template('pytania.html', pytania=dane)
methods=['GET', 'POST']– dodajemy typy żądań, które chcemy obsługiwać, tj. GET (odesłanie zażądanej strony), jak i POST (przesłanie danych z formularza, tj. odpowiedzi, i odesłanie wyników);request– obiekt zawierający informacje związane z żądaniem, m. in. typ żądania i ewentualne dane z formularza;if request.method == 'POST':– instrukcja warunkowa, która wykrywa żądania POST i wykonuje blok kodu zliczający poprawne odpowiedzi;odpowiedzi = request.form– przesyłane dane z formularza zapisujemy w zmiennejodpowiedzi;for pnr, odp in odpowiedzi.items()– w pętli odczytujemy kolejne pary danych, czyli numer pytania i udzieloną odpowiedź;if odp == dane[int(pnr)]['odpok']:– sprawdzamy, czy nadesłana odpowiedź jest zgodna z poprawną, którą odczytujemy z listy pytań.
Zwróćmy uwagę, że wartości zmiennej pnr, czyli numery pytań liczone od zera,
ustaliliśmy wcześniej w szablonie.
Jeżeli nadesłana odpowiedź jest poprawna (if odp == dane[int(pnr)]['odpok']:), tzn. zgadza się
z poprawną odpowiedzią zawartą w liście słowników – doliczamy punkt (punkty += 1).
Informacje o wyniku przekazujemy użytkownikowi za pomocą funkcji flash().
W szablonie wyświetlamy je we wspominanej pętli {% for komunikat in get_flashed_messages() %}.
6.1.5.1. Ćwiczenie
Wstaw w szablonie strony głównej link do strony wyświetlającej pytania.
Uruchom serwer, wejdź na stronę główną, a następnie na stronę z pytaniami.
Zaznacz odpowiedzi i prześlij dane na serwer.
6.1.6. Materiały
Materiały Python 101
udostępniane przez
Centrum Edukacji Obywatelskiej na licencji
Creative Commons Uznanie autorstwa-Na tych samych warunkach 4.0 Międzynarodowa.
- Utworzony:
2026-05-30 o 19:12 w Sphinx 7.3.7
- Autorzy: