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.

Vista di un progetto FastAPI di base all'interno di un IDE.
Vista di un progetto FastAPI di base all’interno di un IDE.

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 metodo GET 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.

Applicazione FastAPI Hello World in un browser web.
Applicazione FastAPI Hello World in un browser web.

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.

Schermata dell'interfaccia Swagger UI per la documentazione.
La documentazione di Swagger UI per FastAPI.

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.

Schermata dell'interfaccia Redoc per la documentazione.
La documentazione di Redoc per FastAPI.

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.

Diagramma della struttura delle tabelle del database per gli esempi CRUD.
Struttura della tabella del database per gli esempi CRUD.

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’utente
  • last_name: Il cognome dell’utente
  • gender: Il genere dell’utente
  • roles, cioè un elenco contenente i ruoli admin e user

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 estende BaseModel, che viene importata da pydantic.
  • 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 di List e avete inserito il modello User
  • Avete creato un database in-memory con quattro utenti, ciascuno con gli attributi richiesti come first_name, last_name, gender e roles. All’utente Eunit sono assegnati i ruoli di admin e user, mentre agli altri tre utenti è assegnato solo il ruolo di user.

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:

Schermata dei dati utente restituiti dalla richiesta GET di FastAPI.
Dati utente recuperati dalla richiesta di lettura del database FastAPI.

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.

Schermata che mostra i parametri della richiesta FastAPI POST.
Parametri per una richiesta FastAPI POST.

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 recupera id, che è una variabile di percorso corrispondente all’id dell’utente.
  • async def delete_user(id: UUID):: Crea la funzione delete_user che recupera id dall’URL.
  • for user in db:: Indica all’applicazione di eseguire un ciclo tra gli utenti del database e di verificare se l’indirizzo id passato corrisponde a un utente del database.
  • db.remove(user): Se id corrisponde a un utente, l’utente verrà eliminato; altrimenti, verrà generato un HTTPException con un codice di stato 404.
Schermata che mostra i parametri della richiesta FastAPI DELETE.
Parametri per una richiesta FastAPI DELETE.

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 variabile id corrisponde all’id dell’utente.
  • Avete creato un metodo chiamato update_user, che accetta la classe UpdateUser e id.
  • Usate un ciclo for per verificare se l’utente associato al parametro id è presente nel database.
  • Controllate se i parametri dell’utente sono is not None (non nulli). Se un parametro, come first_name, last_name, o roles, 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 messaggio Could 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.

Schermata che mostra i parametri per una richiesta FastAPI UPDATE.
Parametri per una richiesta FastAPI UPDATE.

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.

Emmanuel Uchenna

Emmanuel is an experienced, passionate, and enthusiastic software developer and technical writer with proven years of professional experience. He focuses on full-stack web development. He's fluent in ReactJS, JavaScript, VueJS, and NodeJS and familiar with industry-standard technologies such as Git, GitHub, and TDD. He helps individuals, businesses, and brands build responsive, accessible, beautiful, and intuitive websites to improve their online presence. He is also a technical writer for various websites and his own projects.