Utilizziamo i cookie per migliorare la tua esperienza sul sito
CodeWorlds

FastAPI - nowoczesne asynchroniczne API

Witaj ponownie, @name! Darwin tutaj z FastAPI - najnowocześniejszym frameworkiem do budowania API w Pythonie! 🚀⚡

W poprzedniej lekcji nauczyłeś/aś się async/await. Teraz wykorzystamy tę wiedzę z FastAPI - frameworkiem, który jest 3-5× szybszy niż Flask, ma automatyczną walidację, i generu

je dokumentację automatycznie! 🌟

Analogia Safari: Flask to tradycyjna wycieczka safari - sprawdzona, niezawodna. FastAPI to safari na dronach - szybkie, nowoczesne, z GPS-em i automatycznym tracking

iem zwierząt! 🚁🦁

Czym jest FastAPI?

FastAPI to nowoczesny, szybki framework do budowania API stworzony przez Sebastiána Ramíreza w 2018 roku.

Kluczowe cechy:Szybki - comparable z Node.js/Go (dzięki Starlette) ✅ Async native - pełne wsparcie dla async/await ✅ Type hints - wykorzystuje type annotations ✅ Automatyczna walidacja - Pydantic out-of-the-box ✅ Auto docs - Swagger UI + ReDoc automatycznie ✅ Modern Python - Python 3.7+ required

Instalacja FastAPI

1pip install fastapi[all]  # Wszystko (Uvicorn, Pydantic, etc.)
2
3# Lub minimalnie:
4pip install fastapi uvicorn[standard]

Uvicorn = ASGI server (jak Gunicorn dla WSGI)

Hello World FastAPI

1# main.py
2from fastapi import FastAPI
3
4app = FastAPI()
5
6@app.get("/")
7async def root():
8    return {"message": "Hello Safari! 🦁"}
9
10# Uruchom: uvicorn main:app --reload

Uruchom:

1uvicorn main:app --reload

Output:

1INFO: Uvicorn running on http://127.0.0.1:8000
2INFO: Application startup complete.

Otwórz:

  • http://localhost:8000/ → {"message": "Hello Safari! 🦁"}
  • http://localhost:8000/docsAutomatyczna dokumentacja Swagger UI! 📘
  • http://localhost:8000/redoc → Alternatywna dokumentacja ReDoc

FastAPI vs Flask

| FastAPI | Flask | |---------|-------| | Async native | Sync (async możliwe, ale trudne) | | Type hints wymagane | Optional | | Automatyczna walidacja (Pydantic) | Ręczna (Flask-WTF) | | Auto docs (Swagger/ReDoc) | Brak | | 3-5× szybszy | Wolniejszy | | Modern Python (3.7+) | Starsze wersje OK | | API-first | Web apps + API |

Kiedy FastAPI? REST API, microservices, async I/O Kiedy Flask? Web apps z templates, mniejsze projekty

Podstawowe endpointy

1from fastapi import FastAPI
2
3app = FastAPI(title="Safari Database API", version="1.0.0")
4
5# GET - pobierz dane
6@app.get("/species")
7async def list_species():
8    return [
9        {"id": 1, "name": "Lew", "population": 120},
10        {"id": 2, "name": "Słoń", "population": 450}
11    ]
12
13# GET z parametrem w path
14@app.get("/species/{species_id}")
15async def get_species(species_id: int):
16    return {"id": species_id, "name": "Lew", "population": 120}
17
18# POST - dodaj dane
19@app.post("/species")
20async def create_species(name: str, population: int):
21    return {"id": 3, "name": name, "population": population, "status": "created"}
22
23# PUT - aktualizuj
24@app.put("/species/{species_id}")
25async def update_species(species_id: int, name: str, population: int):
26    return {"id": species_id, "name": name, "population": population}
27
28# DELETE - usuń
29@app.delete("/species/{species_id}")
30async def delete_species(species_id: int):
31    return {"id": species_id, "status": "deleted"}

Testuj:

1# GET
2curl http://localhost:8000/species
3
4# POST
5curl -X POST "http://localhost:8000/species?name=Gepard&population=7100"

Query parameters - automatyczna walidacja

FastAPI automatycznie parsuje query params i waliduje typy!

1from fastapi import FastAPI
2
3app = FastAPI()
4
5@app.get("/species")
6async def list_species(
7    skip: int = 0,
8    limit: int = 10,
9    habitat: str | None = None,
10    endangered: bool = False
11):
12    # FastAPI automatycznie:
13    # - parsuje ?skip=10&limit=5&habitat=savanna&endangered=true
14    # - konwertuje typy (str → int, str → bool)
15    # - waliduje (skip musi być int!)
16
17    return {
18        "skip": skip,
19        "limit": limit,
20        "habitat": habitat,
21        "endangered": endangered,
22        "results": ["Lew", "Słoń"]
23    }

Testuj:

1/species                              → skip=0, limit=10, habitat=None, endangered=False
2/species?skip=20&limit=5              → skip=20, limit=5
3/species?habitat=savanna&endangered=1 → habitat="savanna", endangered=True
4/species?skip=abc                     → ERROR: validation error!

FastAPI automatycznie generuje błędy walidacji:

1{
2  "detail": [
3    {
4      "loc": ["query", "skip"],
5      "msg": "value is not a valid integer",
6      "type": "type_error.integer"
7    }
8  ]
9}

Response models - strukturyzowane odpowiedzi

1from fastapi import FastAPI
2from pydantic import BaseModel
3
4app = FastAPI()
5
6class Species(BaseModel):
7    id: int
8    name: str
9    scientific_name: str
10    population: int
11    endangered: bool = False
12
13@app.get("/species/{species_id}", response_model=Species)
14async def get_species(species_id: int):
15    return Species(
16        id=species_id,
17        name="Lew",
18        scientific_name="Panthera leo",
19        population=120,
20        endangered=True
21    )

Korzyści

response_model
:

  • Automatyczna serializacja do JSON
  • Walidacja output
  • Dokumentacja automatycznie pokazuje strukturę
  • Type safety

Pełne Safari API - przykład

1# main.py
2from fastapi import FastAPI, HTTPException
3from pydantic import BaseModel, Field
4from typing import List
5
6app = FastAPI(
7    title="Safari Database API",
8    description="API for managing African wildlife species",
9    version="1.0.0"
10)
11
12# Models
13class SpeciesBase(BaseModel):
14    name: str = Field(..., min_length=2, max_length=100)
15    scientific_name: str
16    population: int = Field(..., ge=0)
17    habitat: str
18
19class SpeciesCreate(SpeciesBase):
20    pass
21
22class Species(SpeciesBase):
23    id: int
24
25    class Config:
26        from_attributes = True
27
28# In-memory database
29species_db: dict[int, Species] = {
30    1: Species(id=1, name="Lew", scientific_name="Panthera leo", population=120, habitat="savanna"),
31    2: Species(id=2, name="Słoń", scientific_name="Loxodonta africana", population=450, habitat="savanna"),
32}
33next_id = 3
34
35# Endpoints
36@app.get("/")
37async def root():
38    return {"message": "Safari Database API", "version": "1.0.0"}
39
40@app.get("/species", response_model=List[Species])
41async def list_species(skip: int = 0, limit: int = 10, habitat: str | None = None):
42    """List all species with pagination"""
43    results = list(species_db.values())
44
45    if habitat:
46        results = [s for s in results if s.habitat == habitat]
47
48    return results[skip : skip + limit]
49
50@app.get("/species/{species_id}", response_model=Species)
51async def get_species(species_id: int):
52    """Get specific species by ID"""
53    if species_id not in species_db:
54        raise HTTPException(status_code=404, detail=f"Species {species_id} not found")
55
56    return species_db[species_id]
57
58@app.post("/species", response_model=Species, status_code=201)
59async def create_species(species: SpeciesCreate):
60    """Create new species"""
61    global next_id
62
63    new_species = Species(id=next_id, **species.dict())
64    species_db[next_id] = new_species
65    next_id += 1
66
67    return new_species
68
69@app.put("/species/{species_id}", response_model=Species)
70async def update_species(species_id: int, species: SpeciesCreate):
71    """Update existing species"""
72    if species_id not in species_db:
73        raise HTTPException(status_code=404, detail="Species not found")
74
75    updated = Species(id=species_id, **species.dict())
76    species_db[species_id] = updated
77
78    return updated
79
80@app.delete("/species/{species_id}")
81async def delete_species(species_id: int):
82    """Delete species"""
83    if species_id not in species_db:
84        raise HTTPException(status_code=404, detail="Species not found")
85
86    del species_db[species_id]
87    return {"status": "deleted", "id": species_id}

Uruchom:

1uvicorn main:app --reload

Testuj API:

1# Lista
2curl http://localhost:8000/species
3
4# Konkretny gatunek
5curl http://localhost:8000/species/1
6
7# Dodaj
8curl -X POST http://localhost:8000/species \
9  -H "Content-Type: application/json" \
10  -d '{"name":"Gepard","scientific_name":"Acinonyx jubatus","population":7100,"habitat":"savanna"}'
11
12# Aktualizuj
13curl -X PUT http://localhost:8000/species/1 \
14  -H "Content-Type: application/json" \
15  -d '{"name":"Lew","scientific_name":"Panthera leo","population":150,"habitat":"savanna"}'
16
17# Usuń
18curl -X DELETE http://localhost:8000/species/3

Automatyczna dokumentacja

FastAPI automatycznie generuje interaktywną dokumentację!

Swagger UI: http://localhost:8000/docs

  • Interaktywne testowanie API
  • "Try it out" button dla każdego endpoint
  • Automatyczne formularze

ReDoc: http://localhost:8000/redoc

  • Czytelna dokumentacja
  • Świetna dla developerów

OpenAPI JSON: http://localhost:8000/openapi.json

  • Raw OpenAPI 3.0 schema
  • Dla narzędzi zewnętrznych

Podsumowanie

W tej lekcji nauczyłeś/aś się:

  • ✅ Czym jest FastAPI i po co go używać
  • ✅ Instalacja FastAPI + Uvicorn
  • ✅ Hello World i podstawowe endpointy
  • ✅ GET, POST, PUT, DELETE
  • ✅ Path parameters i query parameters
  • ✅ Response models z Pydantic
  • ✅ HTTPException dla błędów
  • ✅ Automatyczna dokumentacja (Swagger/ReDoc)
  • ✅ Pełne Safari Database API

Następna lekcja: Darwin pokaże Ci Pydantic v2 - potężny system walidacji danych z FastAPI! 📊✅

Vai a CodeWorlds