- Bir FastAPI uygulaması oluşturmak ve
fastapi devya dauvicornile yerelde çalıştırmak - Yol ve sorgu parametrelerini türlerle tanımlamak, JSON gövdesini bir Pydantic modeliyle doğrulamak
- Doğru durum kodlarını döndürmek ve API'yi
/docsveTestClientile kontrol etmek
Önceki derste istemciydik ve başkasının API'sine istek gönderiyorduk. Şimdi rolleri değiştirip kendi sunucumuzu yazacağız. FastAPI modern bir Python çatısıdır: fonksiyon parametrelerindeki tür ipuçlarını (type hints) kullanarak gelen veriyi kendisi doğrular, JSON'a çevirir ve etkileşimli belgeler oluşturur. Bir mobil uygulama için arka uç, küçük bir mikroservis ya da API olarak sunulan bir makine öğrenmesi modeli: FastAPI bunların hepsi için popüler bir seçimdir.
İlk uygulama ve yerelde çalıştırma
Bir sunucu tarayıcıda çalışamaz; bu yüzden bu dersin kodu burada çalıştırılmaz, onu kendi bilgisayarında (Python 3.10 ya da daha yeni) dene. @app.get('/yol') dekoratörü bir fonksiyonu o adrese gelen GET isteklerine bağlar; fonksiyonun döndürdüğü sözlük otomatik olarak bir JSON yanıtına dönüşür.
from fastapi import FastAPI
app = FastAPI(title='Educora Demo API')
@app.get('/')
def root():
return {'message': 'Hello from FastAPI'}
@app.get('/square/{number}')
def square(number: int):
return {'number': number, 'square': number ** 2}
@app.get('/greet')
def greet(name: str, lang: str = 'en'):
greetings = {'en': 'Hello', 'az': 'Salam', 'ru': 'Привет', 'tr': 'Merhaba'}
word = greetings.get(lang, 'Hello')
return {'text': f'{word}, {name}!'}main.py dosyası. {number} bir yol parametresidir; name ve lang yolda olmadığı için sorgu parametreleridir; lang'ın varsayılan değeri olduğu için isteğe bağlıdır.- 1Sanal ortam oluştur
Proje klasöründe
python -m venv .venvçalıştır ve ortamı etkinleştir: Windows'ta.venv\Scripts\activate, Linux ve macOS'tasource .venv/bin/activate. - 2FastAPI'yi kur
pip install "fastapi[standard]"— FastAPI ile birlikteuvicornsunucusu vefastapikomutu da kurulur. - 3Sunucuyu başlat
fastapi dev main.py(ya dauvicorn main:app --reload). Sunucuhttp://127.0.0.1:8000adresinde çalışır ve dosya değiştiğinde kendini yeniden başlatır. - 4Belgeleri aç
Tarayıcıda
http://127.0.0.1:8000/docssayfasını aç; tüm uç noktalar orada listelenir ve “Try it out” düğmesiyle doğrudan denenebilir.
curl http://127.0.0.1:8000/square/12
curl "http://127.0.0.1:8000/greet?name=Aysel&lang=az"
curl http://127.0.0.1:8000/square/abc{"number":12,"square":144}
{"text":"Salam, Aysel!"}
{"detail":[{"type":"int_parsing","loc":["path","number"],"msg":"Input should be a valid integer, unable to parse string as an integer","input":"abc"}]}abc bir tam sayı olmadığı için FastAPI fonksiyonu hiç çağırmaz ve hatanın nerede olduğunu açıklayan bir yanıtla 422 kodunu döndürür. Windows PowerShell'de curl yerine curl.exe yaz.Pydantic modelleriyle REST API
Bir POST isteğinin JSON gövdesini bir Pydantic modeli tanımlar: BaseModel'den türeyen bir sınıf alanları ve türlerini listeler, Field ise ek koşullar koyar (örneğin 1–100 karakterlik bir başlık). Fonksiyonun dönüş türü (-> Task) yanıtı da doğrular ve fazla alanları ayıklar. Görevler için küçük bir API kuralım; kolaylık olsun diye veriler bellekteki bir sözlükte tutuluyor.
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, Field
app = FastAPI(title='Educora Tasks API')
class TaskIn(BaseModel):
title: str = Field(min_length=1, max_length=100)
subject: str = 'python'
done: bool = False
class Task(TaskIn):
id: int
tasks: dict[int, Task] = {}
@app.post('/tasks', status_code=201)
def create_task(task: TaskIn) -> Task:
new = Task(id=len(tasks) + 1, **task.model_dump())
tasks[new.id] = new
return newtasks.py, 1. bölüm: modeller ve oluşturma. İstemci id göndermez, onu sunucu atar; bu yüzden giriş (TaskIn) ve çıkış (Task) modelleri ayrıdır.@app.get('/tasks')
def list_tasks(subject: str | None = None, limit: int = 10) -> list[Task]:
found = [t for t in tasks.values() if subject is None or t.subject == subject]
return found[:limit]
@app.get('/tasks/{task_id}')
def get_task(task_id: int) -> Task:
if task_id not in tasks:
raise HTTPException(status_code=404, detail='Task not found')
return tasks[task_id]tasks.py, 2. bölüm: okuma. HTTPException fonksiyonu durdurur ve istemciye 404 koduyla {"detail": "Task not found"} gönderir. Sunucuyu fastapi dev tasks.py ile başlat.| İstek | Ne yapar | Yanıt |
|---|---|---|
POST /tasks | yeni bir görev oluşturur | 201 ya da 422 (geçersiz gövde) |
GET /tasks?subject=python&limit=5 | filtrelenmiş bir liste döndürür | 200 |
GET /tasks/{task_id} | tek bir görevi döndürür | 200 ya da 404 |
API'yi test etmek
TestClient, gerçek bir sunucu başlatmadan uygulamayı doğrudan çağırır; istekler ve yanıtlar tamamen gerçektir. Bu, pytest testleri için idealdir: kodu her değiştirdiğinde tüm uç noktaları saniyeler içinde kontrol edebilirsin.
from fastapi.testclient import TestClient
from tasks import app
client = TestClient(app)
r = client.post('/tasks', json={'title': 'Learn FastAPI'})
print(r.status_code, r.json())
client.post('/tasks', json={'title': 'Revise SQL', 'subject': 'sql'})
print(client.get('/tasks', params={'subject': 'python'}).json())
r = client.get('/tasks/99')
print(r.status_code, r.json())
r = client.post('/tasks', json={'title': ''})
print(r.status_code, r.json()['detail'][0]['msg'])201 {'title': 'Learn FastAPI', 'subject': 'python', 'done': False, 'id': 1}
[{'title': 'Learn FastAPI', 'subject': 'python', 'done': False, 'id': 1}]
404 {'detail': 'Task not found'}
422 String should have at least 1 characterField(min_length=1) kuralını bozar; Pydantic isteği fonksiyona ulaşmadan reddeder. subject gönderilmediğinde varsayılan 'python' değeri kullanılır.Önemli noktalar
app = FastAPI()ile@app.get(...)ve@app.post(...)dekoratörleri fonksiyonları adreslere bağlar; döndürülen sözlük JSON olur.- Yoldaki
{ad}bir yol parametresidir, diğer argümanlar sorgu parametreleridir; türler otomatik olarak doğrulanır (hatada 422). - Pydantic'in
BaseModelveFieldyapıları JSON gövdesini tanımlar ve doğrular;status_code=201veHTTPException(404)doğru yanıtlar verir. - Yerelde çalıştırma:
pip install "fastapi[standard]", ardındanfastapi dev main.py; belgeler/docsve/redocadreslerindedir. TestClientAPI'yi sunucu olmadan test eder; gerçek verileri bellekte değil, bir veritabanında sakla.
Kendini test et
10 soru. Her doğru cevap XP kazandırır.
@app.get('/users/{user_id}') ile def get_user(user_id: int, full: bool = False) fonksiyonunda full nedir?