FastAPI är en snabb och lätt webbram för att bygga moderna gränssnitt för tillämpningsprogrammering med hjälp av Python 3.6 och senare. I den här handledningen så går vi igenom grunderna för att bygga en app med FastAPI, och du får lära dig lite om varför detta nominerades som ett av de bästa ramverken med öppen källkod år 2021.

När du väl är redo att utveckla dina egna FastAPI-appar så behöver du inte leta länge efter en plats där du kan hosta dem. Kinsta’s tjänster för applikations- och databashosting erbjuder en ”Platform As a Service” som är stark på Python.

Låt oss först lära oss grunderna.

Fördelar med FastAPI

Nedan följer några av de fördelar som FastAPI-ramverket ger ett projekt.

  • Hastighet: Som namnet antyder så är FastAPI ett mycket snabbt ramverk. Hastigheten är jämförbar med Go och Node.js, som allmänt anses vara bland de snabbaste alternativen för att bygga API: er.
  • Lätt att lära sig och koda: FastAPI har redan räknat ut nästan allt som du behöver för att göra ett produktionsklart API. Som utvecklare som använder FastAPI så behöver du inte koda allt från grunden. Med endast några få rader kod så kan du ha ett RESTful API som är redo för distribuering.
  • Omfattande dokumentation: FastAPI använder OpenAPI-dokumentationsstandarderna, så att dokumentation kan genereras dynamiskt. Dokumentationen innefattar detaljerad information om FastAPI: s ändpunkter, svar, parametrar och returkoder.
  • API: er med färre fel: FastAPI stöder anpassad datavalidering, vilket gör att utvecklare kan bygga API:er med färre fel. FastAPI: s utvecklare skryter med att ramverket resulterar i så mycket som 40 % färre mänskligt orsakade fel.
  • Typtips: Modulen types introducerades i Python 3.5. Den gör det möjligt att deklarera type för en variabel. När typen av en variabel deklareras så kan IDE: er ge ett bättre stöd och förutsäga fel mer exakt.

Hur man kommer igång med FastAPI

För att följa den här handledningen och komma igång med FastAPI så måste du först göra några saker.

Se till att du har en texteditor/IDE för programmerare, exempelvis Visual Studio Code. Andra alternativ är Sublime Text och Espresso.

Det är vanligt att dina Pythonprogram och deras instanser körs i virtuella miljöer. Virtuella miljöer gör det möjligt att köra olika paketuppsättningar och konfigurationer samtidigt och undvika konflikter på grund av inkompatibla paketversioner.

För att skapa en virtuell miljö så öppnar du din terminal och kör det här kommandot:

$ python3 -m venv env

Du måste även aktivera den virtuella miljön. Kommandot för att göra detta varierar beroende på vilket operativsystem och skal som du använder. Här är några exempel på CLI-aktivering för ett antal 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

(Vissa IDE: er med Python-kunskap kan även konfigureras för att aktivera den aktuella virtuella miljön)

Nu kan du installera FastAPI:

$ pip3 install fastapi

FastAPI är ett ramverk för att bygga API: er, men för att testa dina API: er så behöver du en lokal webbserver. Uvicorn är en blixtsnabb ASGI-webbserver (Asynchronous Server Gateway Interface) för Python som är utmärkt för utveckling. För att installera Uvicorn så kör du det här kommandot:

$ pip3 install "uvicorn[standard]"

När installationen har lyckats så skapar du en fil med namnet main.py i projektets arbetskatalog. Denna fil kommer att vara din applikationsstartpunkt.

Visa ett grundläggande FastAPI-projekt i ett IDE.
Visa ett grundläggande FastAPI-projekt i ett IDE.

Ett snabbt FastAPI-exempel

Du kommer att testa din FastAPI-installation genom snabb konfigurering av en exempeländpunkt. Klistra in följande kod i din fil main.py och spara sedan filen:

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

Ovanstående utdrag skapar en grundläggande FastAPI-slutpunkt. Nedan följer en sammanfattning av vad varje rad gör:

  • from fastapi import FastAPI: Funktionaliteten för ditt API tillhandahålls av FastAPI Python-klassen.
  • app = FastAPI(): Detta skapar en FastAPI-instans.
  • @app.get("/"): Detta är en Python-dekorator som anger för FastAPI att funktionen nedanför den ska ansvara för hanteringen av förfrågningar.
  • @app.get("/"): Detta är en dekorator som anger vägen. Detta skapar en GET -metod på webbplatsens sökväg. Resultatet returneras sedan av den inplacerade funktionen.
  • Andra möjliga operationer som används för att kommunicera är @app.post(), @app.put(), @app.delete(), @app.options(), @app.head(), @app.patch() och @app.trace().

I filkatalogen så kör du följande kommando i terminalen för att starta API-servern:

$ uvicorn main:app --reload

I det här kommandot så är main namnet på din modul. Objektet app är en instans av din applikation och importeras till ASGI-servern. Flaggan --reload anger att servern ska laddas om automatiskt när du gör ändringar.

Du bör se något liknande 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.

Navigera till http://localhost:8000 i din webbläsare för att bekräfta att ditt API fungerar. Du bör se ”Hello”: ”World” som ett JSON-objekt på sidan. Detta visar hur enkelt det är att skapa ett API med FastAPI. Allt som du behövde göra var att definiera en rutt och returnera din Python-ordbok, vilket syns på rad sex i utklippet ovan.

Hello World-applikationen hos FastAPI i en webbläsare.
Hello World-applikationen hos FastAPI i en webbläsare.

Användning av typtips

Om du använder Python så är du van vid att ange variabler med grundläggande datatyper som int, str, float och bool. Från och med Python’s version 3.9 har det dock införts avancerade datastrukturer. Detta gör att du kan arbeta med datastrukturer som dictionaries, tuples och lists. Med FastAPI: s typhänvisningar så kan du strukturera schemat för dina data med hjälp av pydantiska modeller och sedan använda de pydantiska modellerna för att typhänvisa och dra nytta av den datavalidering som tillhandahålls.

I exemplet nedan så demonstreras användningen av typtips i Python med en enkel prisberäknare för 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))

Observera att typtips inte ändrar hur din kod körs.

Interaktiv API-dokumentation i FastAPI

FastAPI använder Swagger UI för att tillhandahålla en automatisk interaktiv API-dokumentation. För att komma åt den, navigera till http://localhost:8000/docs så kommer du att se en skärm med alla dina slutpunkter, metoder och scheman.

Swagger UI: s dokumentation för FastAPI.
Swagger UI: s dokumentation för FastAPI.

Denna automatiska, webbläsarbaserade API-dokumentation tillhandahålls av FastAPI och du behöver inte göra något annat för att dra nytta av den.

En alternativ webbläsarbaserad API-dokumentation, som också tillhandahålls av FastAPI, är Redoc. För att få tillgång till Redoc så navigerar du till http://localhost:8000/redoc, där du kommer att få en lista över dina slutpunkter, metoder och deras respektive svar.

Redoc’s dokumentation för FastAPI.
Redoc’s dokumentation för FastAPI.

Upprättande av rutter i FastAPI

Med dekoratorn @app så kan du ange ruttens metod, t.ex. @app.get eller @app.post, som stöder GET, POST, PUT och DELETE, samt de mindre vanliga alternativen HEAD, PATCH och TRACE.

Att bygga din app med FastAPI

I den här handledningen så får du en genomgång av hur du bygger en CRUD-applikation med FastAPI. Applikationen kommer att kunna:

  • Skapa en användare
  • Läsa en användares databaspost
  • Uppdatera en befintlig användare
  • Ta bort en viss användare

För att utföra dessa CRUD-operationer så kommer du att skapa metoder som exponerar API-slutpunkterna. Resultatet kommer att bli en minnesdatabas som kan lagra en lista över användare.

Exempel på databasens tabellstruktur för CRUD.
Exempel på databasens tabellstruktur för CRUD.

Du kommer att använda biblioteket pydantic för att utföra datavalidering och inställningshantering med hjälp av Python-typannotationer. I den här handledningen så kommer du att deklarera formen för dina data som klasser med attribut.

Den här handledningen kommer att använda databasen i minnet. Detta är för att komma igång snabbt med att använda FastAPI för att bygga dina API: er. För produktion så kan du dock använda dig av vilken databas som helst, t.ex. PostgreSQL, MySQL, SQLite eller till och med Oracle.

Att bygga appen

Du börjar med att skapa din användarmodell. Användarmodellen kommer att ha följande attribut:

  • id: En universell unik identifierare (UUID)
  • first_name: Användarens förnamn
  • last_name: Användarens efternamn
  • gender: Användarens kön
  • roles: En lista som innehåller rollerna admin och user

Börja med att skapa en ny fil som heter models.py i din arbetskatalog och klistra sedan in följande kod i models.py för att skapa din modell:


# 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 koden ovan:

  • Din klass User utökar BaseModel, som sedan importeras från pydantic.
  • Du har definierat användarens attribut enligt ovan.

Nästa steg är att skapa din databas. Ersätt innehållet i filen main.py med följande kod:


# 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 initialiserade db med en List-typ och skickade in modellen User
  • Du skapade en minnesdatabas med fyra användare, var och en med de nödvändiga attributen first_name, last_name, gender och roles. Användaren Eunit tilldelas rollerna admin och user, medan de andra tre användarna endast tilldelas rollen user.

Läs databasposter

Du har framgångsrikt konfigurerat din minnesdatabas och fyllt den med användare, så nästa steg är att konfigurera en slutpunkt som returnerar en lista över alla användare. Det är här som FastAPI kommer in i bilden.

I din fil main.py så klistrar du in följande kod precis under din slutpunkt Hello World:


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

Koden definierar slutpunkten /api/v1/users och skapar en asynkron funktion, get_users, som returnerar allt innehåll i databasen, db.

Spara din fil så kan du testa din användarslutpunkt. Kör följande kommando i terminalen för att starta API-servern:

$ uvicorn main:app --reload

Navigera till http://localhost:8000/api/v1/users i din webbläsare. Detta bör ge en lista över alla dina användare, som du ser nedan:

Användardata hämtad av FastAPI-databasläsningsförfrågan.
Användardata hämtad av FastAPI-databasläsningsförfrågan.

I det här skedet så kommer din fil main.py att se ut så här:


# 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

Skapa databasposter

Nästa steg är att skapa en slutpunkt för att skapa en ny användare i din databas. Klistra in följande utdrag i din fil main.py:


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

I det här stycket så har du definierat slutpunkten för att skicka in en ny användare och använt dig av dekoratorn @app.post för att skapa en POST -metod.

Du har även skapat funktionen create_user, som accepterar user i modellen User, och bifogat (lagt till) den nyskapade user till databasen, db. Slutligen så returnerar slutpunkten ett JSON-objekt med den nyskapade användarens id.

Du måste använda den automatiska API-dokumentationen som tillhandahålls av FastAPI för att testa din slutpunkt, som ovan. Detta beror på att du inte kan göra en postförfrågan med hjälp av webbläsaren. Navigera till http://localhost:8000/docs för att testa med hjälp av den dokumentation som tillhandahålls av SwaggerUI.

Parametrar för en FastAPI POST-förfrågan
Parametrar för en FastAPI POST-förfrågan

Radera databasposter

Eftersom du bygger en CRUD-app så måste din applikation ha möjlighet att ta bort en specificerad resurs. I den här handledningen så kommer du att skapa en slutpunkt för att ta bort en användare.

Klistra in följande kod i din fil 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."
 )

Här är en uppdelning linje för linje av hur koden fungerar:

  • @app.delete("/api/v1/users/{id}"): Du skapade slutpunkten delete med hjälp av dekoratorn @app.delete(). Sökvägen är fortfarande /api/v1/users/{id}, men sedan hämtas id, som är en sökvägsvariabel som motsvarar användarens id.
  • async def delete_user(id: UUID):: Du skapar funktionen delete_user, som hämtar id från webbadressen.
  • for user in db:: Detta säger åt applikationen att gå igenom användarna i databasen och kontrollera om id matchar en användare i databasen.
  • db.remove(user): Om id matchar en användare så raderas användaren, annars så skickas en HTTPException med statuskoden 404.
Parametrar för en FastAPI DELETE-förfrågan.
Parametrar för en FastAPI DELETE-förfrågan.

Uppdatera databasposter

Du ska skapa en slutpunkt för att uppdatera en användares uppgifter. De uppgifter som kan uppdateras omfattar följande parametrar: first_name, , last_name, och roles.

I din fil models.py så klistrar du in följande kod under din modell User, dvs. efter klassen User(BaseModel)::

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

I det här utdraget så är klassen UpdateUser en förlängning av BaseModel. Du ställer sedan in de uppdaterbara användarparametrarna, exempelvis first_name, last_name och roles, som valfria.

Nu ska du skapa en slutpunkt för att uppdatera en viss användares uppgifter. I din fil main.py så klistrar du in följande kod efter @app.delete-dekoratorn:

# 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 koden ovan så har du gjort följande:

  • Skapat @app.put("/api/v1/users/{id}")—slutpunkten för uppdatering. Den har variabel-parametern id som motsvarar användarens id.
  • Skapat en metod som heter update_user, som tar emot klassen UpdateUser och id.
  • Använt en for -slinga för att kontrollera om den användare som är associerad med överlämnat id finns i databasen.
  • Kontrollerat om någon av användarens parametrar är is not None (inte noll). Om någon parameter, t.ex. first_name, last_name eller roles, inte är noll, så uppdateras den.
  • Om operationen är framgångsrik så returneras användaridentiteten.
  • Om användaren inte kunde lokaliseras, så uppstår undantaget HTTPException med statuskoden 404 och meddelandet Could not find user with id: {id}.

För att testa den här slutpunkten så måste du se till att din Uvicorn-server är igång. Om den inte är igång, så kan du ange det här kommandot:

uvicorn main:app --reload

Nedan visas en skärmdump av testet.

Parametrar för en FastAPI UPDATE-förfrågan.
Parametrar för en FastAPI UPDATE-förfrågan.

Sammanfattning

I den här handledningen så har du lärt dig mer om FastAPI-ramverket för Python och sett med egna ögon hur snabbt som du kan få igång en FastAPI-driven applikation. Du har lärt dig hur man bygger CRUD API-slutpunkter med hjälp av ramverket – skapa, läsa, uppdatera och radera databasposter.

Om du vill ta din webbapplikationsutveckling till nästa nivå så ska du se till att kolla in Kinsta’s plattform för applikations- och databashosting. Precis som FastAPI så är den kraftfullt enkel.

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.