FastAPI è un framework web veloce e leggero per la creazione di moderne interfacce di programmazione di applicazioni utilizzando Python 3.6 o superiore. In questo tutorial vi spiegheremo le basi della costruzione di un’applicazione con FastAPI e vi faremo capire perché è stato nominato come uno dei migliori framework open-source del 2021.
Quando avrete tutto pronto a sviluppare le vostre applicazioni FastAPI, non dovrete cercare lontano per trovare un posto dove ospitarle. I servizi di hosting di applicazioni e di hosting di database di Kinsta offrono una piattaforma come servizio che si basa su Python.
Impariamo prima le basi.
Vantaggi di FastAPI
Di seguito elenchiamo alcuni dei vantaggi che il framework FastAPI apporta a un progetto.
- Velocità: Come suggerisce il nome, FastAPI è un framework molto veloce. La sua velocità è paragonabile a quella di Go e Node.js, che sono generalmente considerati tra le opzioni più veloci per la creazione di API.
- Facile da imparare e da codificare: FastAPI ha già previsto quasi tutto ciò di cui avrete bisogno per realizzare un’API pronta per la produzione. In qualità di developer che usa FastAPI, non dovrete codificare tutto da zero. Con poche righe di codice potete avere un’API RESTful pronta per la distribuzione.
- Documentazione completa: FastAPI usa gli standard di documentazione OpenAPI, quindi la documentazione può essere generata dinamicamente. Questa documentazione fornisce informazioni dettagliate sugli endpoint, le risposte, i parametri e i codici di ritorno di FastAPI.
- API con meno bug: FastAPI supporta la convalida personalizzata dei dati, il che consente a chi sviluppa di creare API con meno bug. Sviluppatrici e sviluppatori di FastAPI si vantano del fatto che il framework produce meno bug indotti dall’uomo, fino al 40% in meno.
- Suggerimenti sui tipi: Il modulo dei tipi è stato introdotto in Python 3.5. Questo modulo vi permette di dichiarare il tipo
type
di una variabile. Quando il tipo di una variabile viene dichiarato, gli IDE sono in grado di fornire un supporto migliore e di prevedere gli errori con maggiore precisione.
Come Iniziare a Usare FastAPI
Per seguire questo tutorial e iniziare a usare FastAPI, dovete prima fare alcune cose.
Verificate di avere un editor di testo/IDE per developer, come Visual Studio Code. Altre opzioni sono Sublime Text ed Espresso.
È una pratica comune avere le vostre applicazioni Python e le loro istanze in esecuzione in ambienti virtuali. Gli ambienti virtuali permettono di eseguire contemporaneamente diversi set di pacchetti e configurazioni ed evitano conflitti dovuti a versioni di pacchetti incompatibili.
Per creare un ambiente virtuale, aprite il vostro terminale ed eseguite questo comando:
$ python3 -m venv env
Dovrete anche attivare l’ambiente virtuale. Il comando per farlo varia a seconda del sistema operativo e della shell che state usando. Ecco alcuni esempi di attivazione CLI per diversi ambienti:
# On Unix or MacOS (bash shell):
/path/to/venv/bin/activate
# On Unix or MacOS (csh shell):
/path/to/venv/bin/activate.csh
# On Unix or MacOS (fish shell):
/path/to/venv/bin/activate.fish
# On Windows (command prompt):
pathtovenvScriptsactivate.bat
# On Windows (PowerShell):
pathtovenvScriptsActivate.ps1
(Alcuni IDE Python-aware possono anche essere configurati per attivare l’ambiente virtuale corrente.)
Ora installate FastAPI:
$ pip3 install fastapi
FastAPI è un framework per la creazione di API, ma per testare le vostre API avrete bisogno di un server web locale. Uvicorn è un server web Asynchronous Server Gateway Interface (ASGI) velocissimo per Python, ottimo per lo sviluppo. Per installare Uvicorn, eseguite questo comando:
$ pip3 install "uvicorn[standard]"
Una volta completata l’installazione, create un file chiamato main.py nella directory di lavoro del vostro progetto. Questo file sarà il punto di ingresso della vostra applicazione.
Un Rapido Esempio di FastAPI
Per testare la vostra installazione di FastAPI, impostate rapidamente un endpoint di esempio. Nel vostro file main.py, incollate il seguente codice e salvate il file:
# main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"greeting":"Hello world"}
Lo snippet qui sopra crea un endpoint FastAPI di base. Di seguito trovate un riassunto di ciò che fa ogni riga:
from fastapi import FastAPI
: La funzionalità della vostra API è fornita dalla classe FastAPI di Python.app = FastAPI()
: Create un’istanza FastAPI.@app.get("/")
: Si tratta di un decoratore python che specifica a FastAPI che la funzione sottostante è responsabile della gestione delle richieste.@app.get("/")
: Si tratta di un decoratore che specifica il percorso. Crea un metodoGET
sulla rotta del sito. Il risultato viene restituito dalla funzione wrapped.- Altre possibili operazioni usate per comunicare sono
@app.post()
,@app.put()
,@app.delete()
,@app.options()
,@app.head()
,@app.patch()
e@app.trace()
.
Nella directory dei file, eseguite il seguente comando nel vostro terminale per avviare il server API:
$ uvicorn main:app --reload
In questo comando, main
è il nome del vostro modulo. L’oggetto app
è un’istanza della vostra applicazione e viene importato nel server ASGI. Il flag --reload
indica al server di ricaricarsi automaticamente quando si apportano modifiche.
Dovreste vedere qualcosa di simile nel vostro terminale:
$ uvicorn main:app --reload
INFO: Will watch for changes in these directories: ['D:\WEB DEV\Eunit\Tests\fast-api']
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [26888] using WatchFiles
INFO: Started server process [14956]
INFO: Waiting for application startup.
INFO: Application startup complete.
Nel vostro browser, andate su http://localhost:8000
per confermare che l’API funziona. Dovreste vedere “Hello”: “World” come oggetto JSON nella pagina. Questo dimostra quanto sia facile creare un’API con FastAPI. Tutto ciò che dovete fare è definire una rotta e restituire il vostro dizionario Python, come si vede alla riga 6 dello snippet qui sopra.
Usare i Suggerimenti di Tipo
Se usate Python, siete abituati ad annotare le variabili con i tipi di dati di base come int
, str
, float
e bool
. Tuttavia, a partire dalla versione 3.9 di Python, sono state introdotte strutture di dati avanzate. Questo vi permette di lavorare con strutture di dati come dictionaries
, tuples
e lists
. Con i suggerimenti di tipo di FastAPI, potete strutturare lo schema dei vostri dati usando i template pydantic e poi usare i template pydantic per i suggerimenti di tipo e beneficiare della validazione dei dati che vi viene fornita.
Nell’esempio che segue, l’uso dei suggerimenti di tipo in Python è dimostrato con un semplice calcolatore del prezzo dei pasti, calculate_meal_fee
:
def calculate_meal_fee(beef_price: int, meal_price: int) -> int:
total_price: int = beef_price + meal_price
return total_price
print("Calculated meal fee", calculate_meal_fee(75, 19))
Notate che i suggerimenti di tipo non modificano l’esecuzione del codice.
Documentazione API Interattiva di FastAPI
FastAPI usa Swagger UI per fornire una documentazione interattiva automatica delle API. Per accedervi, navigate su http://localhost:8000/docs
e vedrete una schermata con tutti i vostri endpoint, metodi e schemi.
Questa documentazione automatica dell’API basata sul browser è fornita da FastAPI e non dovete fare altro per usufruirne.
Un’alternativa alla documentazione API basata sul browser, anch’essa fornita da FastAPI, è Redoc. Per accedere a Redoc, andate su http://localhost:8000/redoc
, dove vi verrà presentato un elenco dei vostri endpoint, dei metodi e delle rispettive risposte.
Impostare i Percorsi in FastAPI
Il decoratore @app
vi permette di specificare il metodo del percorso, come @app.get
o @app.post
, e supporta GET
, POST
, PUT
, e DELETE
, oltre alle opzioni meno comuni, HEAD
, PATCH
, e TRACE
.
Costruire un’App con FastAPI
In questo tutorial vi illustriamo la costruzione di un’applicazione CRUD con FastAPI. L’applicazione sarà in grado di:
- Creare un utente
- Leggere il record del database di un utente
- Aggiornare un utente esistente
- Eliminare un particolare utente
Per eseguire queste operazioni CRUD, creerete dei metodi che espongono gli endpoint dell’API. Il risultato sarà un database in-memory in grado di memorizzare un elenco di utenti.
Userete la libreria pydantic per eseguire la convalida dei dati e la gestione delle impostazioni utilizzando le annotazioni di tipo Python. Ai fini di questo tutorial, dichiarerete la forma dei vostri dati come classi con attributi.
Questo tutorial utilizzerà il database in-memory. Questo per iniziare rapidamente a utilizzare FastAPI per creare le vostre API. Tuttavia, per la produzione, potete usare qualsiasi database a vostra scelta, come PostgreSQL, MySQL, SQLite o persino Oracle.
Creare l’Applicazione
Inizierete creando il vostro modello utente. Il modello utente avrà i seguenti attributi:
id
: Un identificatore univoco universale (UUID)first_name
: Il nome dell’utentelast_name
: Il cognome dell’utentegender
: Il genere dell’utenteroles
, cioè un elenco contenente i ruoliadmin
euser
Iniziate creando un nuovo file chiamato models.py nella vostra directory di lavoro, quindi incollate il seguente codice in models.py per creare il vostro modello:
# models.py
from typing import List, Optional
from uuid import UUID, uuid4
from pydantic import BaseModel
from enum import Enum
from pydantic import BaseModel
class Gender(str, Enum):
male = "male"
female = "female"
class Role(str, Enum):
admin = "admin"
user = "user"
class User(BaseModel):
id: Optional[UUID] = uuid4()
first_name: str
last_name: str
gender: Gender
roles: List[Role]
Nel codice precedente:
- La vostra classe
User
estendeBaseModel
, che viene importata dapydantic
. - Avete definito gli attributi dell’utente, come discusso in precedenza.
Il passo successivo è la creazione del database. Sostituite il contenuto del file main.py con il seguente codice:
# main.py
from typing import List
from uuid import uuid4
from fastapi import FastAPI
from models import Gender, Role, User
app = FastAPI()
db: List[User] = [
User(
id=uuid4(),
first_name="John",
last_name="Doe",
gender=Gender.male,
roles=[Role.user],
),
User(
id=uuid4(),
first_name="Jane",
last_name="Doe",
gender=Gender.female,
roles=[Role.user],
),
User(
id=uuid4(),
first_name="James",
last_name="Gabriel",
gender=Gender.male,
roles=[Role.user],
),
User(
id=uuid4(),
first_name="Eunit",
last_name="Eunit",
gender=Gender.male,
roles=[Role.admin, Role.user],
),
]
In main.py:
- Avete inizializzato
db
con un tipo diList
e avete inserito il modelloUser
- Avete creato un database in-memory con quattro utenti, ciascuno con gli attributi richiesti come
first_name
,last_name
,gender
eroles
. All’utenteEunit
sono assegnati i ruoli diadmin
euser
, mentre agli altri tre utenti è assegnato solo il ruolo diuser
.
Leggere i Record del Database
Avete configurato correttamente il vostro database in-memory e lo avete popolato di utenti, quindi il passo successivo è quello di configurare un endpoint che restituisca un elenco di tutti gli utenti. Qui entra in gioco FastAPI.
Nel file main.py, incollate il seguente codice appena sotto l’endpoint Hello World
:
# main.py
@app.get("/api/v1/users")
async def get_users():
return db
Questo codice definisce l’endpoint /api/v1/users
e crea una funzione asincrona, get_users
, che restituisce tutti i contenuti del database, db
.
Salvate il file e testate il vostro endpoint utente. Eseguite il seguente comando nel vostro terminale per avviare il server API:
$ uvicorn main:app --reload
Nel vostro browser, navigate su http://localhost:8000/api/v1/users
. Questo dovrebbe restituire un elenco di tutti i vostri utenti, come mostrato di seguito:
A questo punto, il vostro file main.py avrà il seguente aspetto:
# main.py
from typing import List
from uuid import uuid4
from fastapi import FastAPI
from models import Gender, Role, User
app = FastAPI()
db: List[User] = [
User(
id=uuid4(),
first_name="John",
last_name="Doe",
gender=Gender.male,
roles=[Role.user],
),
User(
id=uuid4(),
first_name="Jane",
last_name="Doe",
gender=Gender.female,
roles=[Role.user],
),
User(
id=uuid4(),
first_name="James",
last_name="Gabriel",
gender=Gender.male,
roles=[Role.user],
),
User(
id=uuid4(),
first_name="Eunit",
last_name="Eunit",
gender=Gender.male,
roles=[Role.admin, Role.user],
),
]
@app.get("/")
async def root():
return {"Hello": "World",}
@app.get("/api/v1/users")
async def get_users():
return db
Creare i Record del Database
Il passo successivo consiste nel creare un endpoint per creare un nuovo utente nel database. Incollate il seguente frammento nel vostro file main.py:
# main.py
@app.post("/api/v1/users")
async def create_user(user: User):
db.append(user)
return {"id": user.id}
In questo snippet, avete definito l’endpoint per inviare un nuovo utente e avete utilizzato il decoratore @app.post
per creare un metodo POST
.
Avete anche creato la funzione create_user
, che accetta user
del modello User
e ha aggiunto il nuovo utente user
al database, db
. Infine, l’endpoint restituisce un oggetto JSON con l’indirizzo id
dell’utente appena creato.
Per testare il vostro endpoint dovrete usare la documentazione automatica dell’API fornita da FastAPI, come visto sopra. Questo perché non è possibile effettuare una richiesta di post utilizzando il browser web. Navigate su http://localhost:8000/docs
per eseguire il test usando la documentazione fornita da SwaggerUI.
Cancellare i Record del Database
Dato che state realizzando un’applicazione CRUD, la vostra applicazione dovrà avere la possibilità di cancellare una risorsa specifica. In questo tutorial, creerete un endpoint per cancellare un utente.
Incollate il seguente codice nel vostro file main.py:
# main.py
from uuid import UUID
from fastapi HTTPException
@app.delete("/api/v1/users/{id}")
async def delete_user(id: UUID):
for user in db:
if user.id == id:
db.remove(user)
return
raise HTTPException(
status_code=404, detail=f"Delete user failed, id {id} not found."
)
Ecco una descrizione riga per riga di come funziona il codice:
@app.delete("/api/v1/users/{id}")
: Avete creato l’endpoint di cancellazione utilizzando il decoratore@app.delete()
. Il percorso è ancora/api/v1/users/{id}
, ma poi recuperaid
, che è una variabile di percorso corrispondente all’id dell’utente.async def delete_user(id: UUID):
: Crea la funzionedelete_user
che recuperaid
dall’URL.for user in db:
: Indica all’applicazione di eseguire un ciclo tra gli utenti del database e di verificare se l’indirizzoid
passato corrisponde a un utente del database.db.remove(user)
: Seid
corrisponde a un utente, l’utente verrà eliminato; altrimenti, verrà generato unHTTPException
con un codice di stato 404.
Aggiornare i Record del Database
Creerete un endpoint per aggiornare i dati di un utente. I dettagli che possono essere aggiornati includono i seguenti parametri: first_name
, last_name
, e roles
.
Nel vostro file models.py, incollate il seguente codice sotto il template User
, cioè dopo la classe User(BaseModel):
:
# models.py
class UpdateUser(BaseModel):
first_name: Optional[str]
last_name: Optional[str]
roles: Optional[List[Role]]
In questo frammento, la classe UpdateUser
estende BaseModel
. Poi impostate i parametri utente aggiornabili, come first_name
, last_name
e roles
, come opzionali.
Ora create un endpoint per aggiornare i dati di un determinato utente. Nel file main.py, incollate il seguente codice dopo il decoratore @app.delete
:
# main.py
@app.put("/api/v1/users/{id}")
async def update_user(user_update: UpdateUser, id: UUID):
for user in db:
if user.id == id:
if user_update.first_name is not None:
user.first_name = user_update.first_name
if user_update.last_name is not None:
user.last_name = user_update.last_name
if user_update.roles is not None:
user.roles = user_update.roles
return user.id
raise HTTPException(status_code=404, detail=f"Could not find user with id: {id}")
Nel codice precedente, avete fatto quanto segue:
- Avete creato
@app.put("/api/v1/users/{id}")
, l’endpoint di aggiornamento. Il parametro variabileid
corrisponde all’id dell’utente. - Avete creato un metodo chiamato
update_user
, che accetta la classeUpdateUser
eid
. - Usate un ciclo
for
per verificare se l’utente associato al parametroid
è presente nel database. - Controllate se i parametri dell’utente sono
is not None
(non nulli). Se un parametro, comefirst_name
,last_name
, oroles
, non è nullo, viene aggiornato. - Se l’operazione ha successo, viene restituito l’id dell’utente.
- Se l’utente non è stato trovato, viene sollevata un’eccezione
HTTPException
con codice di stato 404 e messaggioCould not find user with id: {id}
.
Per testare questo endpoint, verificate che il vostro server Uvicorn sia in funzione. Se non è in esecuzione, inserite questo comando:
uvicorn main:app --reload
Di seguito è riportata una schermata del test.
Riepilogo
In questo tutorial avete imparato a conoscere il framework FastAPI per Python e avete visto con i vostri occhi quanto velocemente si può realizzare un’applicazione alimentata da FastAPI. Avete imparato a costruire endpoint API CRUD usando il framework: creazione, lettura, aggiornamento e cancellazione di record di database.
Ora, se volete portare lo sviluppo delle vostre applicazioni web a un livello superiore, verificate di dare un’occhiata alla piattaforma di Kinsta per l’hosting di applicazioni e database. Come FastAPI, è davvero semplice.
Lascia un commento