Zbuduj aplikację z FastAPI dla Pythona
Opublikowany: 2022-11-29FastAPI to szybka i lekka platforma internetowa do tworzenia nowoczesnych interfejsów programowania aplikacji przy użyciu języka Python 3.6 i nowszych. W tym samouczku omówimy podstawy tworzenia aplikacji za pomocą FastAPI i dowiesz się, dlaczego została nominowana jako jedna z najlepszych platform open source w 2021 roku.
Gdy będziesz gotowy do tworzenia własnych aplikacji FastAPI, nie będziesz musiał daleko szukać miejsca, aby je hostować. Usługi hostingu aplikacji i hostingu baz danych Kinsta zapewniają platformę jako usługę, która jest silna w Pythonie.
Najpierw nauczmy się podstaw.
Zalety FastAPI
Poniżej przedstawiono niektóre zalety, jakie framework FastAPI wnosi do projektu.
- Szybkość: Jak sama nazwa wskazuje, FastAPI to bardzo szybki framework. Jego szybkość jest porównywalna z Go i Node.js, które są powszechnie uważane za jedne z najszybszych opcji do tworzenia interfejsów API.
- Łatwy do nauczenia i kodowania: FastAPI wymyśliło już prawie wszystko, czego będziesz potrzebować do stworzenia gotowego do produkcji interfejsu API. Jako programista korzystający z FastAPI nie musisz kodować wszystkiego od zera. Wystarczy kilka wierszy kodu, aby przygotować interfejs RESTful API do wdrożenia.
- Obszerna dokumentacja: FastAPI wykorzystuje standardy dokumentacji OpenAPI, dzięki czemu dokumentacja może być generowana dynamicznie. Ta dokumentacja zawiera szczegółowe informacje o punktach końcowych FastAPI, odpowiedziach, parametrach i kodach powrotu.
- Interfejsy API z mniejszą liczbą błędów: FastAPI obsługuje niestandardowe sprawdzanie poprawności danych, co pozwala programistom tworzyć interfejsy API z mniejszą liczbą błędów. Twórcy FastAPI chwalą się, że framework powoduje mniej błędów wywołanych przez człowieka — aż o 40% mniej.
- Wskazówki dotyczące typów: Moduł typów został wprowadzony w Pythonie 3.5. Pozwala to zadeklarować
type
zmiennej. Po zadeklarowaniu typu zmiennej IDE są w stanie zapewnić lepszą obsługę i dokładniej przewidywać błędy.
Jak rozpocząć pracę z FastAPI
Aby postępować zgodnie z tym samouczkiem i rozpocząć pracę z FastAPI, musisz najpierw wykonać kilka czynności.
Upewnij się, że masz edytor tekstu/IDE programisty, taki jak Visual Studio Code. Inne opcje to Sublime Text i Espresso.
Powszechną praktyką jest uruchamianie aplikacji w języku Python i ich instancji w środowiskach wirtualnych. Środowiska wirtualne umożliwiają jednoczesne uruchamianie różnych zestawów pakietów i konfiguracji oraz unikanie konfliktów spowodowanych niekompatybilnymi wersjami pakietów.
Aby utworzyć środowisko wirtualne, otwórz terminal i uruchom to polecenie:
$ python3 -m venv env
Będziesz także musiał aktywować środowisko wirtualne. Polecenie, aby to zrobić, będzie się różnić w zależności od używanego systemu operacyjnego i powłoki. Oto kilka przykładów aktywacji CLI dla wielu środowisk:
# 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
(Niektóre środowiska IDE obsługujące język Python można również skonfigurować tak, aby aktywowały bieżące środowisko wirtualne).
Teraz zainstaluj FastAPI:
$ pip3 install fastapi
FastAPI to platforma do tworzenia interfejsów API, ale do testowania interfejsów API potrzebny jest lokalny serwer WWW. Uvicorn to błyskawiczny serwer sieciowy Asynchronous Server Gateway Interface (ASGI) dla języka Python, który doskonale nadaje się do programowania. Aby zainstalować Uvicorn, uruchom to polecenie:
$ pip3 install "uvicorn[standard]"
Po pomyślnej instalacji utwórz plik o nazwie main.py w katalogu roboczym projektu. Ten plik będzie punktem wejścia aplikacji.
Szybki przykład FastAPI
Przetestujesz instalację FastAPI, szybko konfigurując przykładowy punkt końcowy. W pliku main.py wklej następujący kod, a następnie zapisz plik:
# main.py from fastapi import FastAPI app = FastAPI() @app.get("/") async def root(): return {"greeting":"Hello world"}
Powyższy fragment tworzy podstawowy punkt końcowy FastAPI. Poniżej znajduje się podsumowanie tego, co robi każda linia:
-
from fastapi import FastAPI
: Funkcjonalność twojego API jest zapewniana przez klasę FastAPI Pythona. -
app = FastAPI()
: Tworzy instancję FastAPI. -
@app.get("/")
: To jest dekorator Pythona, który określa FastAPI, że funkcja pod nim jest odpowiedzialna za obsługę żądań. -
@app.get("/")
: To jest dekorator określający trasę. Spowoduje to utworzenie metodyGET
na trasie witryny. Wynik jest następnie zwracany przez opakowaną funkcję. - Inne możliwe operacje używane do komunikacji to
@app.post()
,@app.put()
,@app.delete()
,@app.options()
,@app.head()
,@app.patch()
i@app.trace()
.
W katalogu plików uruchom następujące polecenie w swoim terminalu, aby uruchomić serwer API:
$ uvicorn main:app --reload
W tym poleceniu main
to nazwa twojego modułu. Obiekt app
jest instancją Twojej aplikacji i jest importowany do serwera ASGI. Flaga --reload
mówi serwerowi, aby ładował się automatycznie po wprowadzeniu jakichkolwiek zmian.
Powinieneś zobaczyć coś takiego w swoim terminalu:
$ 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.
W przeglądarce przejdź do http://localhost:8000
, aby potwierdzić, że interfejs API działa. Powinieneś zobaczyć „Hello”: „World” jako obiekt JSON na stronie. To ilustruje, jak łatwo jest stworzyć interfejs API za pomocą FastAPI. Wszystko, co musiałeś zrobić, to zdefiniować trasę i zwrócić słownik Pythona, jak widać w szóstym wierszu powyższego fragmentu.
Korzystanie ze wskazówek typu
Jeśli używasz Pythona, jesteś przyzwyczajony do adnotowania zmiennych za pomocą podstawowych typów danych, takich jak int
, str
, float
i bool
. Jednak od wersji Pythona 3.9 wprowadzono zaawansowane struktury danych. Pozwala to na pracę ze strukturami danych, takimi jak dictionaries
, tuples
i lists
. Dzięki wskazówkom typu FastAPI możesz ustrukturyzować schemat swoich danych za pomocą modeli pydantycznych, a następnie użyć modeli pydantycznych do wpisania podpowiedzi i skorzystania z dostarczonej walidacji danych.
W poniższym przykładzie użycie podpowiedzi typu w Pythonie jest zademonstrowane za pomocą prostego kalkulatora ceny posiłków, 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))
Pamiętaj, że wskazówki dotyczące typów nie zmieniają sposobu działania kodu.
Dokumentacja interaktywnego interfejsu API FastAPI
FastAPI używa Swagger UI do dostarczania automatycznej interaktywnej dokumentacji API. Aby uzyskać do niego dostęp, przejdź do http://localhost:8000/docs
, a zobaczysz ekran ze wszystkimi punktami końcowymi, metodami i schematami.
Ta automatyczna, oparta na przeglądarce dokumentacja API jest dostarczana przez FastAPI i nie musisz robić nic więcej, aby z niej skorzystać.
Alternatywną dokumentacją interfejsu API opartą na przeglądarce, również dostarczaną przez FastAPI, jest Redoc. Aby uzyskać dostęp do Redoc, przejdź do http://localhost:8000/redoc
, gdzie zostanie wyświetlona lista punktów końcowych, metod i ich odpowiednich odpowiedzi.
Konfigurowanie tras w FastAPI
Dekorator @app
umożliwia określenie metody trasy, takiej jak @app.get
lub @app.post
, i obsługuje GET
, POST
, PUT
i DELETE
, a także mniej popularne opcje, HEAD
, PATCH
i TRACE
.
Budowanie aplikacji za pomocą FastAPI
W tym samouczku przeprowadzimy Cię przez proces tworzenia aplikacji CRUD za pomocą FastAPI. Aplikacja będzie mogła:
- Utwórz użytkownika
- Odczyt rekordu bazy danych użytkownika
- Zaktualizuj istniejącego użytkownika
- Usuń określonego użytkownika
Aby wykonać te operacje CRUD, utworzysz metody, które ujawnią punkty końcowe API. Rezultatem będzie baza danych w pamięci, która może przechowywać listę użytkowników.
Będziesz używać biblioteki pydantic do sprawdzania poprawności danych i zarządzania ustawieniami przy użyciu adnotacji typu Python. Na potrzeby tego samouczka zadeklarujesz kształt swoich danych jako klasy z atrybutami.
W tym samouczku zostanie użyta baza danych w pamięci. Ma to na celu szybkie rozpoczęcie korzystania z FastAPI do tworzenia interfejsów API. Jednak do produkcji możesz użyć dowolnej wybranej bazy danych, takiej jak PostgreSQL, MySQL, SQLite, a nawet Oracle.
Tworzenie aplikacji
Zaczniesz od utworzenia modelu użytkownika. Model użytkownika będzie miał następujące atrybuty:
-
id
: uniwersalny unikalny identyfikator (UUID) -
first_name
: Imię użytkownika -
last_name
: Nazwisko użytkownika -
gender
: płeć użytkownika -
roles
, która jest listą zawierającą roleadmin
iuser
Zacznij od utworzenia nowego pliku o nazwie models.py w swoim katalogu roboczym, a następnie wklej następujący kod do models.py , aby utworzyć 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]
W powyższym kodzie:
- Twoja klasa
User
rozszerzaBaseModel
, który jest następnie importowany zpydantic
. - Zdefiniowałeś atrybuty użytkownika, jak omówiono powyżej.
Następnym krokiem jest utworzenie bazy danych. Zastąp zawartość pliku main.py następującym kodem:
# 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], ), ]
w main.py :
- Zainicjowałeś
db
typemList
i przekazałeś w modeluUser
- Utworzono bazę danych w pamięci z czterema użytkownikami, z których każdy ma wymagane atrybuty, takie jak
first_name
,last_name
,gender
iroles
. UżytkownikowiEunit
przypisano roleadmin
iuser
, podczas gdy pozostałym trzem użytkownikom przypisano tylko rolęuser
.
Przeczytaj rekordy bazy danych
Pomyślnie skonfigurowałeś bazę danych w pamięci i wypełniłeś ją użytkownikami, więc następnym krokiem jest skonfigurowanie punktu końcowego, który zwróci listę wszystkich użytkowników. I tu pojawia się FastAPI.
W pliku main.py wklej następujący kod tuż pod punktem końcowym Hello World
:
# main.py @app.get("/api/v1/users") async def get_users(): return db
Ten kod definiuje punkt końcowy /api/v1/users
i tworzy funkcję asynchroniczną get_users
, która zwraca całą zawartość bazy danych db
.
Zapisz plik i możesz przetestować punkt końcowy użytkownika. Uruchom następujące polecenie w swoim terminalu, aby uruchomić serwer API:
$ uvicorn main:app --reload
W przeglądarce przejdź do http://localhost:8000/api/v1/users
. Powinno to zwrócić listę wszystkich użytkowników, jak pokazano poniżej:
Na tym etapie Twój plik main.py będzie wyglądał następująco:
# 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
Utwórz rekordy bazy danych
Następnym krokiem jest utworzenie punktu końcowego w celu utworzenia nowego użytkownika w bazie danych. Wklej następujący fragment kodu do pliku main.py :
# main.py @app.post("/api/v1/users") async def create_user(user: User): db.append(user) return {"id": user.id}
W tym fragmencie zdefiniowałeś punkt końcowy do przesłania nowego użytkownika i wykorzystałeś dekorator @app.post
do utworzenia metody POST
.
Stworzyłeś również funkcję create_user
, która akceptuje user
z modelu User
i dołączyłeś (dodałeś) nowo utworzonego user
do bazy danych, db
. Na koniec punkt końcowy zwraca obiekt JSON o id
nowo utworzonego użytkownika.
Będziesz musiał użyć automatycznej dokumentacji API dostarczonej przez FastAPI, aby przetestować swój punkt końcowy, jak pokazano powyżej. Wynika to z faktu, że nie można wysłać prośby o wysłanie wiadomości za pomocą przeglądarki internetowej. Przejdź do http://localhost:8000/docs
, aby przetestować przy użyciu dokumentacji dostarczonej przez SwaggerUI.
Usuń rekordy bazy danych
Ponieważ budujesz aplikację CRUD, Twoja aplikacja będzie musiała mieć możliwość usunięcia określonego zasobu. W tym samouczku utworzysz punkt końcowy, aby usunąć użytkownika.
Wklej następujący kod do pliku 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." )
Oto podział wiersz po wierszu, jak działa ten kod:
-
@app.delete("/api/v1/users/{id}")
: utworzono punkt końcowy usuwania za pomocą dekoratora@app.delete()
. Ścieżka to nadal/api/v1/users/{id}
, ale następnie pobieraid
, który jest zmienną ścieżki odpowiadającą identyfikatorowi użytkownika. -
async def delete_user(id: UUID):
: Tworzy funkcjędelete_user
, która pobieraid
z adresu URL. -
for user in db:
: mówi aplikacji, aby przechodziła przez użytkowników w bazie danych i sprawdzała, czy przekazanyid
pasuje do użytkownika w bazie danych. -
db.remove(user)
: Jeśliid
pasuje do użytkownika, użytkownik zostanie usunięty; w przeciwnym razie zostanieHTTPException
z kodem stanu 404.
Zaktualizuj rekordy bazy danych
Zamierzasz utworzyć punkt końcowy, aby zaktualizować dane użytkownika. Szczegóły, które można zaktualizować, obejmują następujące parametry: first_name
, last_name
i roles
.
W swoim pliku models.py wklej następujący kod pod swoim modelem User
, czyli po klasie User(BaseModel):
:
# models.py class UpdateUser(BaseModel): first_name: Optional[str] last_name: Optional[str] roles: Optional[List[Role]]
W tym fragmencie klasa UpdateUser
rozszerza BaseModel
. Następnie ustawiasz parametry użytkownika, które można aktualizować, takie jak first_name
, last_name
i roles
, jako opcjonalne.
Teraz utworzysz punkt końcowy, aby zaktualizować dane konkretnego użytkownika. W pliku main.py wklej następujący kod po dekoratorze @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}")
W powyższym kodzie wykonałeś następujące czynności:
- Utworzono
@app.put("/api/v1/users/{id}")
, punkt końcowy aktualizacji. Ma zmiennyid
parametru, który odpowiada identyfikatorowi użytkownika. - Utworzono metodę o nazwie
update_user
, która przyjmuje klasęUpdateUser
iid
. - Użyto pętli
for
, aby sprawdzić, czy użytkownik powiązany z przekazanymid
znajduje się w bazie danych. - Sprawdzono, czy któryś z parametrów użytkownika
is not None
(nie null). Jeśli jakikolwiek parametr, taki jakfirst_name
,last_name
lubroles
, nie ma wartości null, jest aktualizowany. - Jeśli operacja się powiedzie, zwracany jest identyfikator użytkownika.
- Jeśli użytkownik nie został zlokalizowany, zgłaszany jest wyjątek
HTTPException
z kodem stanu 404 i komunikatemCould not find user with id: {id}
.
Aby przetestować ten punkt końcowy, upewnij się, że serwer Uvicorn jest uruchomiony. Jeśli nie jest uruchomiony, wprowadź to polecenie:
uvicorn main:app --reload
Poniżej zrzut ekranu z testu.
Streszczenie
W tym samouczku poznałeś framework FastAPI dla Pythona i przekonałeś się, jak szybko można uruchomić aplikację opartą na FastAPI. Nauczyłeś się, jak budować punkty końcowe CRUD API przy użyciu frameworka — tworzenie, odczytywanie, aktualizowanie i usuwanie rekordów bazy danych.
Teraz, jeśli chcesz przenieść tworzenie aplikacji internetowych na wyższy poziom, koniecznie sprawdź platformę Kinsta do hostingu aplikacji i hostingu baz danych. Podobnie jak FastAPI, jest niezwykle prosty.