====== 5. Server - REST API ====== ===== Cíle cvičení ===== - seznámení s balíčkem (frameworkem) Flask - vytvoření jednoduché statické stránky s vlastním HTML, CSS, využítí knihovny Bootstrap - seznámení s REST API - vytvoření vlástní aplikace využívající REST API ==== Flask ==== V níže uvedeném bloku kódu nejprve importujete objekt Flask z balíčku flask. Poté pomocí něj vytvoříte instanci aplikace Flask a dáte jí jméno app. Předáte speciální proměnnou name, která obsahuje název aktuálního modulu Pythonu. Toto jméno říká instanci, kde se nachází; potřebujete ho, protože Flask v zákulisí nastavuje některé cesty. Jakmile vytvoříte instanci aplikace, můžete ji použít ke zpracování příchozích webových požadavků a odesílání odpovědí uživateli. ''@app.route'' je dekorátor, který změní běžnou funkci jazyka Python na funkci Flask view, která převede návratovou hodnotu funkce na odpověď HTTP, kterou zobrazí klient HTTP, například webový prohlížeč. Funkci ''@app.route()'' předáte hodnotu ''/'', která znamená, že tato funkce bude odpovídat na webové požadavky na adresu URL /, což je hlavní adresa URL. Funkce zobrazení ''hello()'' vrátí jako odpověď HTTP řetězec ''
from flask import Flask # Importing the Flask module from the flask package
app = Flask(__name__) # Creating an instance of the Flask class
@app.route('/') # View function for endpoint '/'
def hello():
return "Hello, World!
"
# Starting a web application at 0.0.0.0.0:5000 with debug mode enabled
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5000, debug=True)
Nyní máte jednoduchou aplikaci Flask v souboru Python s názvem ''app.py'', v dalším kroku aplikaci spustíte a uvidíte výsledek funkce zobrazení hello() vykreslený ve webovém prohlížeči.
Jako layout projektu zvolíme následující strukturu:
/home/user/Projects/flask-tutorial
├── app.py
├── templates/
│ └── index.html
├── static/
│ └── style.css
└── venv/
Adresář ''%%static%%'' bude obsahovat statické soubory jako CSS a JavaScript. Adresář ''%%templates%%'' bude obsahovat šablony HTML pro různé stránky aplikace.
==== Zobrazování HTML stránek ====
Aby naše funkce ''%%hello()%%'' pracovala s HTML, stačí ji změnit takto:
from flask import Flask # Importing the Flask module from the flask package
app = Flask(__name__) # Creating an instance of the Flask class
@app.route('/') # View function for endpoint '/'
def hello():
return "Hi there! Hello, World!", 200
# Starting a web application at 0.0.0.0.0:5000 with debug mode enabled
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5000, debug=True, use_reloader=False)
V tomto případě ''%%hello()%%'' vrací řetězec ve formátu HTML a číslo. Řetězec bude ve výchozím nastavení analyzován jako HTML, zatímco 200 je nepovinný kód HTTP označující úspěšnou odpověď. Ve výchozím nastavení je vrácen kód 200. Tento přístup k zobrazování HTML komponent je ovšem velmi limitující.
Vhodnější je vyžít šablony - vytvoříme šablonu ''index.html'':
NSI App
Hello World!
A ''%%app.py%%'' upravíme následovně:
from flask import Flask, render_template
app = Flask(__name__) # Creating an instance of the Flask class
@app.route('/') # View function for endpoint '/'
def hello():
return render_template('index.html')
# Starting a web application at 0.0.0.0.0:5000 with debug mode enabled
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5000, debug=True, use_reloader=False)
''%%render_template%%'' umožňuje načítat šablony ze složky templates/ (výchozí pro Flask) a stačí je vykreslit pomocí vrácení výstupu.
Nyní přidáme několik JavaScript a CSS stylů. Vestavěný vývojový server Flask ve výchozím nastavení obsluhuje všechny soubory ve složce projektu, které se nacházejí v podsložce ''%%static%%''. V této složce vytvoříme soubory ''%%styles.css%%'' a ''%%script.js%%''
body {
display: flex;
justify-content: center;
align-items: center;
margin: 0;
}
h1 {
font-size: 2em;
}
Pro použití těchto souborů je ještě musíme zahrnout v ''%%index.html%%'':
NSI App
Hello, World!
==== Knihovna Bootstrap ====
Pro použití dalších, složitějších grafických prvků je vhodné použít CSS knihovnu jako Bootstrap, Foundation, … CSS knihovna se v podstatě skládá z několika souborů CSS stylů připravených k použití vývojáři a návrháři webových stránek. Soubory stylů jsou připraveny pro standardní funkce webového designu: nastavení barev, rozvržení, písem, navigačních panelů atd. Obecně jsou soubory stylů podporovány a rozšiřovány o další skriptovací technologie, jako je SASS a JavaScript.
S CSS knihovnou má uživatel k dispozici hotový soubor stylů CSS a k vytvoření webové stránky mu stačí napsat HTML s přesnými třídami, strukturou a ID. Knihovna má již zabudované třídy pro běžné prvky webových stránek - zápatí, posuvník, navigační panel, rozvržení založené na sloupcích atd.
Import CSS Knihovny Bootstrap:
Odkazy jsou dostupné z: [[https://getbootstrap.com/|Bootstrap · The most popular HTML, CSS, and JS library in the world. (getbootstrap.com)]]
NSI app
Toto je text v těle karty.
==== Šablony ve Flasku ====
Hlavní balíček, který se ve Flasku stará o pohledy - šablony je Jinja2 ([[https://jinja.palletsprojects.com/en/3.1.x/|Jinja — Documentation]]), pomocí kterého lze vytvářet formátovaný text s integrovanou logikou. Na rozdíl od funkce formátování v jazyce Python, která umožňuje pouze nahradit značky proměnným obsahem, lze uvnitř šablony řetězce mít řídicí strukturu, například for cyklus.
Šablona může obsahovat proměnné a výrazy, které se při vykreslení šablony nahradí hodnotami, které řídí logiku šablony. Syntaxe šablony je do značné míry inspirována jazykem Django a Python.
Existuje několik druhů oddělovačů. Výchozí oddělovače Jinja jsou nakonfigurovány takto:
* ''%%{% ... %}%%'' - pro výrazy
* ''%%{{ ... }}%%'' - pro výrazy, které se mají vypisovat na výstup šablony
* ''%%{# ... #}%%'' - pro komentáře, které se do výstupu šablony nezahrnují.
Více informací: [[https://jinja.palletsprojects.com/en/3.0.x/templates/#list-of-control-structures|Template Designer Documentation — Jinja Documentation (3.0.x) (palletsprojects.com)]]
=== Oddělení dynamických části od statických ===
V naší webové aplikaci jsou komponenty, které se budou zobrazovat stejně na jakékoli URL - např. ''%%navbar%%''. Místo definování ''%%navbaru%%'' v každé HTML Jinja šabloně můžeme využít **dědičnost šablon**. Ta umožňuje vytvořit základní “kostru” šablony, která obsahuje všechny společné prvky webu a definuje bloky, které mohou podřízené šablony přepisovat.
=== Proměnné v šablonách ===
Proměnné v šablonách jsou definovány kontextovým slovníkem předaným šabloně.
==== REST API ====
REST API (Representational State Transfer Application Programming interface) je jedním z nejpoužívanějším typů API. Je navržený tak, aby byl jednoduchý, flexibilní a snadno školovatelný pro komunikaci mezi klienty a serverem pomocí standardních HTTP metod a formátů dat, jako je JSON.
REST API organizuje datové entity (zdroje) do jedinečných URL adres. Technicky nejde o URL, ale o URI (Uniform Resource Identifiers), které rozlišují různé typy datových zdrojů na serveru. Klient může získat data o zdroji tím, že požádá o přístup k tomuto koncovému bodu pomocí protokolu HTTP.
Zpráva požadavku má velmi specifický formát. Nejdůležitější je //Start// řádek, který obsahuje URI, ke kterému chce klient přistoupit a HTTP metodu požadavku, která signalizuje záměry klienta s daným zdrojem.
Pod Start řádkem se nachází hlavičky, které obsahují metadata o požadavků. Hlavička //accept// může serveru říct, že má připravit data ve specifickém formátu, nebo hlavička //authorisation// může být použita k tomu, aby serveru sdělila, že má klient dostatečná oprávnění pro daný HTTP požadavek. Po hlavičkách následuje tělo, které obsahuje vlastní soubor dat.
Po přijetí zprávy požadavku provede server určitý kód (obvykle čtení z databáze), který může být následně zformátován do zprávy s odpovědí. Začátek zprávy obsahuje stavový kód, který klientovy sděluje, co se stalo s jeho požadavkem. Kódy na úrovni 2xx znamenají, že všechno proběhlo v pořádku, na úrovni 4xx znamenají, že s požadavkem bylo něco špatně, a na úrovni 5xx znamenají, že server selhal.
Po stavovém kódu následují hlavičky odpovědi, které obsahují informace o serveru. Po nich následuje tělo odpovědi, které obsahuje soubor dat a obvykle je formátováno v JSON.
Důležitou součástí této architektury je, že je bez-stavová. To znamená, že obě strany nepotřebují uchovávat žádné informace o sobě navzájem. Každý cyklus požadavek - odpověď je nezávislý na ostatní komunikaci. To vede k dobře fungujícímu chování, které je předvídatelné a spolehlivé.
== HTTP metody ==
Druhou vrstvou REST API jsou HTTP metody, které umožňují klientům provádět různé operace s daty uloženými na serveru. Tyto metody definují způsoby, jakými se klienti mohou dotazovat, vytvářet, aktualizovat a mazat data prostřednictvím jednoduchých HTTP požadavků.
^Metoda^Popis ^
|GET |Metoda GET se používá pro získání dat ze serveru. Klient požádá server o získání konkrétního zdroje a server odpoví informacemi o daném zdroji, pokud existuje. |
|POST |Metoda POST slouží k vytváření nových zdrojů na serveru. Klient pošle serveru nová data a server je uloží jako nový zdroj. |
|PUT |Metoda PUT se používá pro aktualizaci existujících zdrojů na serveru. Klient pošle serveru aktualizovaná data a server je použije k aktualizaci existujícího zdroje.|
|DELETE|Metoda DELETE je určena k mazání zdrojů ze serveru. Klient pošle serveru požadavek na smazání konkrétního zdroje a server odpovídá odebráním tohoto zdroje. |
Správné použití HTTP metod je důležité pro navrhování srozumitelných a efektivních REST API. Každá metoda má svůj vlastní účel a zajišťuje, že API je konzistentní, jednoduché na použití a bezpečné. Použití standardních HTTP metod také umožňuje snadnou integraci s různými nástroji a frameworky pro vývoj.
==== REST API ve Flasku ====
Pro efektivní manipulaci s HTTP požadavky a odpověďmi ve frameworku Flask jsou k dispozici dva důležité balíčky: //request// a //jsonify//. Tyto balíčky umožňují zpracovávání dat v rámci REST API a usnadňuje komunikaci mezi klienty a serverem.
Balíček //request// umožňuje zpracování HTTP požadavků, které klienti odesílají serveru, a poskytuje snadný způsob, jak získat přístup k jednotlivým částem těchto požadavků, jako jsou zdroje, hlavičky nebo metody. Základní funkcionalitou balíčku //request// je získávání dat z požadavků ve formě JSON, formulářů nebo parametrů URL.
@app.route('/tasks', methods=['POST'])
def create_task():
new_task = request.json
new_task['id'] = get_task_id()
tasks.append(new_task)
return jsonify(new_task), 201
Ve funkci ''%%create_task()%%'' používáme ''%%request.json%%'', abychom získali data, která klient posílá v těle požadavku při vytváření nového úkolu. Tato data jsou použita k vytvoření nového úkolu a uložení do seznamu úkolů.
Balíček //request// také umožňuje získání informací o metodě požadavku (''%%request.method%%''), o adrese URL (''%%request.url%%'') nebo o hlavičkách (''%%request.headers%%'').
Balíček //jsonify// umožňuje serializaci dat do formátu JSON a vytvoření odpovědi do formátu JSON.
tasks = [
{"id": 1, "title": "Task 1", "description": "Task 1 desc"},
{"id": 2, "title": "Task 2", "description": "Task 2 desc"},
]
@app.route('/tasks', methods=['GET'])
def get_tasks():
return jsonify(tasks)
// Výstup z jsonify(tasks)
[
{
"id": 1,
"title": "Task 1",
"description": "Task 1 desc"
},
{
"id": 2,
"title": "Task 2",
"description": "Task 2 desc"
}
]