FastAPI er en hurtig og letvægts webframework til opbygning af moderne programmeringsgrænseflader til applikationer ved hjælp af Python 3.6 og derover. I denne vejledning gennemgår vi det grundlæggende i at bygge en app med FastAPI, og du får en fornemmelse af, hvorfor det blev nomineret som en af de bedste open source-frameworks i 2021.

Når du er klar til at udvikle dine egne FastAPI-apps, skal du ikke lede længe for at finde et sted at hoste dem. Kinsta’s Applikation Hosting– og Database Hosting-tjenester giver en Platform as a Service, der er stærk på Python.

Lad os først lære det grundlæggende.

Fordele ved FastAPI

Nedenfor er nogle af de fordele, som FastAPI-framework bringer til et projekt.

  • Hastighed: Som navnet antyder, er FastAPI en meget hurtig ramme. Dens hastighed kan sammenlignes med Go og Node.js, som generelt anses for at være blandt de hurtigste muligheder for at bygge API’er.
  • Let at lære og kode: FastAPI har allerede regnet næsten alt det ud, du skal bruge for at lave en produktionsklar API. Som udvikler, der bruger FastAPI, behøver du ikke at kode alting fra bunden. Med kun få linjer kode kan du have et RESTful API klar til implementering.
  • Omfattende dokumentation: FastAPI bruger OpenAPI-dokumentationsstandarderne, så dokumentation kan genereres dynamisk. Denne dokumentation indeholder detaljerede oplysninger om FastAPI’s endpoints, svar, parametre og returkoder.
  • API’er med færre fejl: FastAPI understøtter brugerdefineret datavalidering, hvilket gør det muligt for udviklere at opbygge API’er med færre fejl. FastAPI’s udviklere praler af, at denne framework resulterer i færre menneskeskabte fejl – helt op til 40% færre.
  • Typehints: Types-modulet blev indført i Python 3.5. Det giver dig mulighed for at deklarere type for en variabel. Når typen af en variabel er deklareret, kan IDE’er give bedre support og forudsige fejl mere præcist.

Sådan kommer du i gang med FastAPI

For at følge denne vejledning og komme i gang med FastAPI skal du først gøre et par ting.

Sørg for, at du har en teksteditor/IDE til programmører, f.eks. Visual Studio Code. Andre muligheder omfatter Sublime Text og Espresso.

Det er en almindelig praksis at have dine Python-apps og deres instanser kørende i virtuelle miljøer. Virtuelle miljøer gør det muligt at køre forskellige pakkesæt og konfigurationer samtidig og undgå konflikter på grund af inkompatible pakkeversioner.

For at oprette et virtuelt miljø skal du åbne din terminal og køre denne kommando:

$ python3 -m venv env

Du skal også aktivere det virtuelle miljø. Kommandoen til at gøre det vil variere afhængigt af det operativsystem og den shell, du bruger. Her er nogle eksempler på CLI-aktivering for en række miljøer:

# 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

(Nogle Python-aware IDE’er kan også konfigureres til at aktivere det aktuelle virtuelle miljø.)

Nu skal du installere FastAPI:

$ pip3 install fastapi

FastAPI er en ramme til opbygning af API’er, men for at teste dine API’er har du brug for en lokal webserver. Uvicorn er en lynhurtig Asynchronous Server Gateway Interface (ASGI) webserver til Python, som er fantastisk til udvikling. For at installere Uvicorn skal du køre denne kommando:

$ pip3 install "uvicorn[standard]"

Når installationen er lykkedes, skal du oprette en fil med navnet main.py i dit projekts arbejdskatalog. Denne fil vil være dit indgangspunkt for applikationen.

Visning af et grundlæggende FastAPI-projekt i et IDE.
Visning af et grundlæggende FastAPI-projekt i et IDE.

Et hurtigt FastAPI-eksempel

Du skal teste din FastAPI-installation ved hurtigt at opsætte et eksempel endpoint. Indsæt følgende kode i din main.py-fil, og gem derefter filen:

# main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
 return {"greeting":"Hello world"}

Ovenstående uddrag skaber et grundlæggende FastAPI-endpoint. Nedenfor er en oversigt over, hvad hver linje gør:

  • from fastapi import FastAPI: Funktionaliteten for din API leveres af FastAPI Python-klassen.
  • app = FastAPI(): Dette opretter en FastAPI-instans.
  • @app.get("/"): Dette er en python-dekorator, der angiver over for FastAPI, at funktionen under den er ansvarlig for håndteringen af anmodninger.
  • @app.get("/"): Dette er en dekorator, der angiver ruten. Dette opretter en GET -metode på webstedets rute. Resultatet returneres derefter af den indpakkede funktion.
  • Andre mulige operationer, der bruges til at kommunikere, omfatter @app.post(), @app.put(), @app.delete(), @app.options(), @app.head(), @app.patch() og @app.trace().

I filmappen skal du køre følgende kommando i din terminal for at starte API-serveren:

$ uvicorn main:app --reload

I denne kommando er main navnet på dit modul. Objektet app er en instans af dit program og importeres til ASGI-serveren. Flaget --reload fortæller serveren, at den skal genindlæses automatisk, når du foretager ændringer.

Du bør se noget, der ligner dette i din terminal:

 $ 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.

Naviger til http://localhost:8000 i din browser for at bekræfte, at din API fungerer. Du bør se “Hello”: “World” som et JSON-objekt på siden. Dette illustrerer, hvor nemt det er at oprette en API med FastAPI. Det eneste, du skulle gøre, var at definere en rute og returnere din Python-ordbog, som det ses på linje seks i ovenstående uddrag.

En FastAPI Hello World-applikation, der kører i en webbrowser.
FastAPI Hello World-applikation i en webbrowser.

Brug af typehints

Hvis du bruger Python, er du vant til at anmærke variabler med grundlæggende datatyper som int, str, float og bool. Fra Python version 3.9 blev der imidlertid indført avancerede datastrukturer. Dette giver dig mulighed for at arbejde med datastrukturer som dictionaries, tuples og lists. Med FastAPI’s typehints kan du strukturere skemaet for dine data ved hjælp af pydantiske modeller og derefter bruge de pydantiske modeller til at give typehints og drage fordel af den datavalidering, der er til rådighed.

I eksemplet nedenfor demonstreres brugen af typehints i Python med en simpel prisberegner til måltider, 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))

Bemærk, at typehints ikke ændrer den måde, som din kode kører på.

FastAPI interaktiv API-dokumentation

FastAPI bruger Swagger UI til at levere automatisk interaktiv API-dokumentation. For at få adgang til den skal du navigere til http://localhost:8000/docs, og du vil se en skærm med alle dine endpoints, metoder og skemaer.

Skærmbillede af Swagger UI-grænsefladen til dokumentation.
Swagger UI’s dokumentation for FastAPI.

Denne automatiske, browserbaserede API-dokumentation leveres af FastAPI, og du behøver ikke at gøre noget andet for at udnytte den.

En alternativ browserbaseret API-dokumentation, som også leveres af FastAPI, er Redoc. For at få adgang til Redoc skal du navigere til http://localhost:8000/redoc, hvor du vil blive præsenteret for en liste over dine endpoints, metoderne og deres respektive svar.

Skærmbillede af Redoc-grænsefladen til dokumentation.
Redoc’s dokumentation for FastAPI.

Opsætning af ruter i FastAPI

Med dekoratoren @app kan du angive rutens metode, f.eks. @app.get eller @app.post, og den understøtter GET, POST, PUT og DELETE, samt de mindre almindelige muligheder HEAD, PATCH og TRACE.

Opbygning af din app med FastAPI

I denne vejledning vil du blive gennemgå opbygningen af en CRUD-applikation med FastAPI. Applikationen vil være i stand til at:

  • Oprettelse af en bruger
  • Læs en brugers databasepost
  • Opdatering af en eksisterende bruger
  • Sletning af en bestemt bruger

For at udføre disse CRUD-operationer vil du oprette metoder, der eksponerer API-slutpunkterne. Resultatet vil være en in-memory-database, der kan gemme en liste over brugere.

Diagram over databasetabelstruktur for CRUD-eksempler.
Database tabelstruktur for CRUD-eksempler.

Du skal bruge pydantic-biblioteket til at udføre datavalidering og indstillinger ved hjælp af Python-typeannotationer. Med henblik på denne vejledning vil du erklære formen af dine data som klasser med attributter.

Denne tutorial vil bruge in-memory-databasen. Dette er for hurtigt at få dig i gang med at bruge FastAPI til at opbygge dine API’er. Til produktion kan du dog gøre brug af en hvilken som helst database efter eget valg, f.eks. PostgreSQL, MySQL, SQLite eller endda Oracle.

Opbygning af appen

Du begynder med at oprette din brugermodel. Brugermodellen vil have følgende attributter:

  • id: En universel unik identifikator (UUID)
  • first_name: Brugerens fornavn
  • last_name: Brugerens efternavn
  • gender: Brugerens køn
  • roles, som er en liste med admin og user roller

Start med at oprette en ny fil ved navn models.py i din arbejdskatalog, og indsæt derefter følgende kode i models.py for at oprette din model:


# 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]

I ovenstående kode:

  • Din User -klasse udvider BaseModel, som derefter importeres fra pydantic.
  • Du har defineret brugerens attributter som beskrevet ovenfor.

Det næste skridt er at oprette din database. Udskift indholdet af din main.py-fil med følgende kode:


# 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],
 ),
]

I main.py:

  • Du initialiserede db med en type List, og du indgav User -modellen
  • Du oprettede en in-memory-database med fire brugere, hver med de nødvendige attributter såsom first_name, last_name, gender og roles. Brugeren Eunit er tildelt rollerne admin og user, mens de tre andre brugere kun er tildelt rollen user.

Read Database Records

Du har oprettet din in-memory-database og udfyldt den med brugere, så det næste skridt er at oprette et slutpunkt, der returnerer en liste over alle brugere. Det er her, FastAPI kommer ind i billedet.

I din main.py-fil indsætter du følgende kode lige under dit Hello World endpoint:


# main.py
 @app.get("/api/v1/users")
 async def get_users():
 return db

Denne kode definerer endpointet /api/v1/users og opretter en asynkron funktion, get_users, som returnerer alt indhold i databasen, db.

Gem din fil, og du kan teste dit brugerendpunkt. Kør følgende kommando i din terminal for at starte API-serveren:

$ uvicorn main:app --reload

Naviger til http://localhost:8000/api/v1/users i din browser. Dette skulle give en liste over alle dine brugere, som vist nedenfor:

Skærmbillede af brugerdata returneret af FastAPI GET-anmodning.
Brugerdata hentet af FastAPI database read request.

På dette tidspunkt vil din main.py-fil se således ud:


# 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

Opret Database Records

Det næste trin er at oprette et endpoint til at oprette en ny bruger i din database. Indsæt følgende uddrag i din main.py-fil:


# main.py
@app.post("/api/v1/users")
async def create_user(user: User):
 db.append(user)
 return {"id": user.id}

I dette uddrag har du defineret slutpunktet til at indsende en ny bruger og gjort brug af @app.post decorator til at oprette en POST -metode.

Du oprettede også funktionen create_user, som accepterer user i modellen User, og du tilføjede (tilføjede) den nyligt oprettede user til databasen, db. Endelig returnerer endpoint et JSON-objekt med den nyoprettede brugers id.

Du skal bruge den automatiske API-dokumentation fra FastAPI til at teste dit endpoint, som det fremgår ovenfor. Dette skyldes, at du ikke kan foretage en postanmodning ved hjælp af webbrowseren. Naviger til http://localhost:8000/docs for at teste ved hjælp af den dokumentation, der leveres af SwaggerUI.

Skærmbillede, der viser parametre for FastAPI POST-anmodning.
Parametre til en FastAPI POST-anmodning

Sletning af databa records

Da du bygger en CRUD-app, skal din applikation have mulighed for at slette en bestemt ressource. I denne tutorial vil du oprette et endpoint til at slette en bruger.

Indsæt følgende kode i din main.py-fil:


# 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."
 )

Her er en linje-for-linje opdeling af, hvordan denne kode fungerer:

  • @app.delete("/api/v1/users/{id}"): Du har oprettet slette-endpoint ved hjælp af @app.delete() -dekoratoren. Stien er stadig /api/v1/users/{id}, men derefter hentes id, som er en stivariabel, der svarer til brugerens id.
  • async def delete_user(id: UUID):: Opretter funktionen delete_user, som henter id fra URL’en.
  • for user in db:: Dette fortæller appen, at den skal gennemløbe brugerne i databasen og kontrollere, om den overførte id passer til en bruger i databasen.
  • db.remove(user): Hvis id passer til en bruger, slettes brugeren, ellers sendes en HTTPException med statuskode 404.
Skærmbillede, der viser parametre for FastAPI DELETE-anmodning.
Parametre for en FastAPI DELETE-anmodning.

Opdatering af database records

Du skal oprette et endpoint til at opdatere en brugers oplysninger. De detaljer, der kan opdateres, omfatter følgende parametre: first_name, , last_name, og roles.

I din models.py-fil indsætter du følgende kode under din User -model, dvs. efter User(BaseModel): -klassen:

 # models.py
 class UpdateUser(BaseModel):
 first_name: Optional[str]
 last_name: Optional[str]
 roles: Optional[List[Role]]

I dette uddrag udvider klassen UpdateUser BaseModel . Derefter indstiller du de opdaterbare brugerparametre, f.eks. first_name, last_name og roles, til at være valgfrie.

Nu opretter du et slutpunkt for at opdatere en bestemt brugers oplysninger. I din fil main.py indsætter du følgende kode efter @app.delete decorator:

# 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}")

I ovenstående kode har du gjort følgende:

  • Oprettede @app.put("/api/v1/users/{id}"), opdateringsslutpunktet. Det har en variabel parameter id, der svarer til brugerens id.
  • Der blev oprettet en metode kaldet update_user, som indeholder klassen UpdateUser og id.
  • Brugte et for loop til at kontrollere, om den bruger, der er knyttet til den overgivne id, findes i databasen.
  • Kontrolleret, om nogen af brugerens parametre er is not None (ikke nul). Hvis en parameter, f.eks. first_name, last_name eller roles, ikke er nul, opdateres den.
  • Hvis operationen er vellykket, returneres bruger-id’et.
  • Hvis brugeren ikke kunne findes, opstår der en HTTPException undtagelse med statuskode 404 og en meddelelse Could not find user with id: {id}.

For at teste dette endpoint skal du sikre dig, at din Uvicorn-server kører. Hvis den ikke kører, skal du indtaste denne kommando:

uvicorn main:app --reload

Nedenfor er et skærmbillede af testen.

Skærmbillede, der viser parametre for en UPDATE-anmodning.
Parametre for en FastAPI UPDATE-anmodning.

Opsummering

I denne tutorial har du lært om FastAPI-rammen til Python og har selv set, hvor hurtigt du kan få en FastAPI-drevet applikation op at køre. Du har lært at opbygge CRUD API endpoints ved hjælp af dette framework – oprettelse, læsning, opdatering og sletning af database records.

Hvis du nu ønsker at tage din webapp-udvikling til det næste niveau, skal du huske at tjekke Kinstas platform til applikationshosting og databasehosting. Ligesom FastAPI er den kraftfuldt enkel.

Emmanuel Uchenna

Emmanuel er en erfaren, passioneret og entusiastisk softwareudvikler og teknisk skribent med dokumenteret års professionel erfaring. Han fokuserer på full-stack webudvikling. Han er flydende i ReactJS, JavaScript, VueJS og NodeJS og er bekendt med industristandardteknologier såsom Git, GitHub og TDD. Han hjælper enkeltpersoner, virksomheder og brands med at bygge responsive, tilgængelige, smukke og intuitive hjemmesider for at forbedre deres online tilstedeværelse. Han er også teknisk skribent for forskellige hjemmesider og egne projekter.