Crea un'app con FastAPI per Python
Pubblicato: 2022-11-29FastAPI è un framework web veloce e leggero per la creazione di moderne interfacce di programmazione delle applicazioni utilizzando Python 3.6 e versioni successive. In questo tutorial, illustreremo le basi della creazione di un'app con FastAPI e avrai un'idea del motivo per cui è stato nominato come uno dei migliori framework open source del 2021.
Una volta che sei pronto a sviluppare le tue app FastAPI, non dovrai cercare lontano per trovare un posto dove ospitarle. I servizi di hosting di applicazioni e hosting di database di Kinsta forniscono una piattaforma come servizio forte di Python.
Impariamo prima le basi.
Vantaggi di FastAPI
Di seguito sono riportati 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 considerate tra le opzioni più veloci per la creazione di API.
- Facile da imparare e codificare: FastAPI ha già capito quasi tutto ciò di cui avrai bisogno per creare un'API pronta per la produzione. Come sviluppatore che utilizza FastAPI, non è necessario codificare tutto da zero. Con solo poche righe di codice, puoi avere un'API RESTful pronta per la distribuzione.
- Documentazione completa: FastAPI utilizza gli standard di documentazione OpenAPI, quindi la documentazione può essere generata dinamicamente. Questa documentazione fornisce informazioni dettagliate su endpoint, risposte, parametri e codici restituiti di FastAPI.
- API con meno bug: FastAPI supporta la convalida dei dati personalizzata, che consente agli sviluppatori di creare API con meno bug. Gli sviluppatori di FastAPI si vantano che il framework si traduce in un minor numero di bug indotti dall'uomo, fino al 40% in meno.
- Suggerimenti sui tipi: il modulo types è stato introdotto in Python 3.5. Ciò consente di dichiarare il
type
di una variabile. Quando viene dichiarato il tipo di una variabile, gli IDE sono in grado di fornire un supporto migliore e prevedere gli errori in modo più accurato.
Come iniziare con FastAPI
Per seguire questo tutorial e iniziare con FastAPI, devi prima fare alcune cose.
Assicurati di disporre di un editor di testo/IDE per programmatori, ad esempio Visual Studio Code. Altre opzioni includono Sublime Text ed Espresso.
È prassi comune che le app Python e le relative istanze vengano eseguite in ambienti virtuali. Gli ambienti virtuali consentono l'esecuzione simultanea di set di pacchetti e configurazioni diversi ed evitano conflitti dovuti a versioni di pacchetto incompatibili.
Per creare un ambiente virtuale, apri il tuo terminale ed esegui questo comando:
$ python3 -m venv env
Dovrai anche attivare l'ambiente virtuale. Il comando per farlo varierà a seconda del sistema operativo e della shell che stai utilizzando. Di seguito sono riportati alcuni esempi di attivazione della CLI per una serie di 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): \path\to\venv\Scripts\activate.bat # On Windows (PowerShell): \path\to\venv\Scripts\Activate.ps1
(Alcuni IDE compatibili con Python possono anche essere configurati per attivare l'ambiente virtuale corrente.)
Ora, installa FastAPI:
$ pip3 install fastapi
FastAPI è un framework per la creazione di API, ma per testare le tue API avrai bisogno di un server web locale. Uvicorn è un server Web ASGI (Asynchronous Server Gateway Interface) velocissimo per Python, ottimo per lo sviluppo. Per installare Uvicorn, esegui questo comando:
$ pip3 install "uvicorn[standard]"
Al termine dell'installazione, crea un file denominato main.py all'interno della directory di lavoro del tuo progetto. Questo file sarà il punto di ingresso dell'applicazione.
Un esempio rapido di FastAPI
Verificherai l'installazione di FastAPI configurando rapidamente un endpoint di esempio. Nel tuo file main.py , incolla il seguente codice, quindi salva il file:
# main.py from fastapi import FastAPI app = FastAPI() @app.get("/") async def root(): return {"greeting":"Hello world"}
Il frammento precedente crea un endpoint FastAPI di base. Di seguito è riportato un riepilogo di ciò che ciascuna riga fa:
-
from fastapi import FastAPI
: la funzionalità per la tua API è fornita dalla classe Python FastAPI. -
app = FastAPI()
: crea un'istanza FastAPI. -
@app.get("/")
: questo è un decoratore python che specifica a FastAPI che la funzione sottostante è responsabile della gestione delle richieste. -
@app.get("/")
: questo è un decoratore che specifica il percorso. Questo crea un metodoGET
sul percorso del sito. Il risultato viene quindi restituito dalla funzione avvolto. - Altre possibili operazioni utilizzate per comunicare includono
@app.post()
,@app.put()
,@app.delete()
,@app.options()
,@app.head()
,@app.patch()
e@app.trace()
.
Nella directory dei file, esegui il seguente comando nel tuo terminale per avviare il server API:
$ uvicorn main:app --reload
In questo comando, main
è il nome del tuo modulo. L'oggetto app
è un'istanza della tua applicazione e viene importato nel server ASGI. Il flag --reload
indica al server di ricaricarsi automaticamente quando si apportano modifiche.
Dovresti vedere qualcosa di simile nel tuo 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 tuo browser, vai a http://localhost:8000
per confermare che l'API funziona. Dovresti vedere "Hello": "World" come oggetto JSON sulla pagina. Questo illustra quanto sia facile creare un'API con FastAPI. Tutto quello che dovevi fare era definire un percorso e restituire il tuo dizionario Python, come visto alla riga sei dello snippet sopra.
Utilizzo dei suggerimenti sul tipo
Se usi Python, sei abituato ad annotare le variabili con tipi di dati di base come int
, str
, float
e bool
. Tuttavia, dalla versione 3.9 di Python, sono state introdotte strutture dati avanzate. Ciò consente di lavorare con strutture di dati quali dictionaries
, tuples
ed lists
. Con i suggerimenti di tipo di FastAPI, puoi strutturare lo schema dei tuoi dati utilizzando i modelli pydantic e quindi utilizzare i modelli pydantic per digitare il suggerimento e trarre vantaggio dalla convalida dei dati fornita.
Nell'esempio seguente, l'uso dei suggerimenti di tipo in Python è dimostrato con un semplice calcolatore del prezzo del pasto, 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))
Tieni presente che i suggerimenti sul tipo non modificano il modo in cui viene eseguito il codice.
Documentazione API interattiva FastAPI
FastAPI utilizza l'interfaccia utente di Swagger per fornire la documentazione API interattiva automatica. Per accedervi, vai su http://localhost:8000/docs
e vedrai una schermata con tutti i tuoi endpoint, metodi e schemi.
Questa documentazione API automatica basata su browser è fornita da FastAPI e non è necessario fare nient'altro per trarne vantaggio.
Una documentazione API alternativa basata su browser, anch'essa fornita da FastAPI, è Redoc. Per accedere a Redoc, vai a http://localhost:8000/redoc
, dove ti verrà presentato un elenco dei tuoi endpoint, i metodi e le rispettive risposte.
Impostazione di percorsi in FastAPI
Il @app
decorator ti consente di specificare il metodo del percorso, come @app.get
o @app.post
, e supporta GET
, POST
, PUT
e DELETE
, così come le opzioni meno comuni, HEAD
, PATCH
e TRACE
.
Crea la tua app con FastAPI
In questo tutorial, verrà illustrato come creare un'applicazione CRUD con FastAPI. L'applicazione sarà in grado di:
- Crea un utente
- Leggere il record del database di un utente
- Aggiorna un utente esistente
- Elimina un particolare utente
Per eseguire queste operazioni CRUD, creerai metodi che espongono gli endpoint API. Il risultato sarà un database in memoria in grado di memorizzare un elenco di utenti.
Utilizzerai 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, dichiarerai la forma dei tuoi dati come classi con attributi.
Questa esercitazione utilizzerà il database in memoria. Questo per iniziare rapidamente a utilizzare FastAPI per creare le tue API. Tuttavia, per la produzione, puoi utilizzare qualsiasi database di tua scelta, come PostgreSQL, MySQL, SQLite o persino Oracle.
Creazione dell'app
Inizierai creando il tuo 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 sesso dell'utente -
roles
, che è un elenco contenente i ruoliadmin
euser
Inizia creando un nuovo file chiamato models.py nella tua directory di lavoro, quindi incolla il seguente codice in models.py per creare il tuo 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 sopra:
- La tua classe
User
estendeBaseModel
, che viene quindi importato dapydantic
. - Hai definito gli attributi dell'utente, come discusso sopra.
Il prossimo passo è creare il tuo database. Sostituisci il contenuto del tuo 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 :
- Hai inizializzato
db
con un tipo diList
e passato il modelloUser
- Hai creato un database in memoria con quattro utenti, ciascuno con gli attributi richiesti come
first_name
,last_name
,gender
eroles
. All'utenteEunit
vengono assegnati i ruoli diadmin
euser
, mentre agli altri tre utenti viene assegnato solo il ruolo diuser
.
Leggi i record del database
Hai configurato correttamente il tuo database in memoria e lo hai popolato con gli utenti, quindi il passaggio successivo consiste nell'impostare un endpoint che restituirà un elenco di tutti gli utenti. È qui che entra in gioco FastAPI.
Nel tuo file main.py , incolla il seguente codice appena sotto il tuo 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 tutto il contenuto del database, db
.
Salva il tuo file e puoi testare il tuo endpoint utente. Esegui il seguente comando nel tuo terminale per avviare il server API:
$ uvicorn main:app --reload
Nel tuo browser, vai a http://localhost:8000/api/v1/users
. Questo dovrebbe restituire un elenco di tutti i tuoi utenti, come mostrato di seguito:
A questo punto, il tuo file main.py avrà questo 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
Crea record di database
Il passaggio successivo consiste nel creare un endpoint per creare un nuovo utente nel database. Incolla il seguente frammento nel tuo 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 frammento, hai definito l'endpoint per inviare un nuovo utente e hai utilizzato il decoratore @app.post
per creare un metodo POST
.
Hai anche creato la funzione create_user
, che accetta l' user
del modello User
, e hai aggiunto (aggiunto) l' user
appena creato al database, db
. Infine, l'endpoint restituisce un oggetto JSON id
dell'utente appena creato.
Dovrai utilizzare la documentazione API automatica fornita da FastAPI per testare il tuo endpoint, come visto sopra. Questo perché non puoi effettuare una richiesta di pubblicazione utilizzando il browser web. Passare a http://localhost:8000/docs
per testare utilizzando la documentazione fornita da SwaggerUI.
Elimina i record del database
Poiché stai creando un'app CRUD, la tua applicazione dovrà avere la possibilità di eliminare una risorsa specificata. Per questo tutorial, creerai un endpoint per eliminare un utente.
Incolla il seguente codice nel tuo 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 ripartizione riga per riga di come funziona quel codice:
-
@app.delete("/api/v1/users/{id}")
: hai creato l'endpoint di eliminazione utilizzando il decoratore@app.delete()
. Il percorso è ancora/api/v1/users/{id}
, ma poi recupera l'id
, che è una variabile di percorso corrispondente all'id dell'utente. -
async def delete_user(id: UUID):
: Crea la funzionedelete_user
, che recupera l'id
dall'URL. -
for user in db:
: indica all'app di scorrere gli utenti nel database e verificare se l'id
passato corrisponde a un utente nel database. -
db.remove(user)
: se l'id
corrisponde a un utente, l'utente verrà eliminato; in caso contrario,HTTPException
con codice di stato 404.
Aggiorna i record del database
Stai per creare un endpoint per aggiornare i dettagli di un utente. I dettagli che possono essere aggiornati includono i seguenti parametri: first_name
, last_name
e roles
.
Nel tuo file models.py , incolla il seguente codice sotto il tuo modello 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
. Quindi imposta i parametri utente aggiornabili, ad esempio first_name
, last_name
e roles
, come facoltativi.
Ora creerai un endpoint per aggiornare i dettagli di un particolare utente. Nel tuo file main.py , incolla 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 sopra, hai fatto quanto segue:
- Creato
@app.put("/api/v1/users/{id}")
, l'endpoint di aggiornamento. Ha un parametroid
variabile che corrisponde all'id dell'utente. - Creato un metodo chiamato
update_user
, che accetta la classeUpdateUser
eid
. - Utilizzato un ciclo
for
per verificare se l'utente associatoid
passato è nel database. - Controllato se uno qualsiasi dei parametri dell'utente
is not None
(non nullo). Se un parametro, ad esempiofirst_name
,last_name
oroles
, non è nullo, viene aggiornato. - Se l'operazione ha esito positivo, viene restituito l'ID utente.
- Se l'utente non è stato individuato, viene generata un'eccezione
HTTPException
con un codice di stato 404 e un messaggioCould not find user with id: {id}
.
Per testare questo endpoint, assicurati che il tuo server Uvicorn sia in esecuzione. Se non è in esecuzione, inserisci questo comando:
uvicorn main:app --reload
Di seguito uno screenshot del test.
Riepilogo
In questo tutorial, hai imparato a conoscere il framework FastAPI per Python e hai visto di persona quanto velocemente puoi far funzionare un'applicazione basata su FastAPI. Hai imparato a creare endpoint API CRUD utilizzando il framework: creando, leggendo, aggiornando ed eliminando i record del database.
Ora, se volete portare lo sviluppo della vostra app web al livello successivo, assicuratevi di dare un'occhiata alla piattaforma di Kinsta per l'hosting di applicazioni e l'hosting di database. Come FastAPI, è estremamente semplice.