Ana içeriğe geç

Input ve Output için Ayrı OpenAPI Schema'ları (Ya da Değil)

🌐 Translation by AI and humans

This translation was made by AI guided by humans. 🤝

It could have mistakes of misunderstanding the original meaning, or looking unnatural, etc. 🤖

You can improve this translation by helping us guide the AI LLM better.

English version

Pydantic v2 yayınlandığından beri, üretilen OpenAPI eskisine göre biraz daha net ve doğru. 😎

Hatta bazı durumlarda, aynı Pydantic model için OpenAPI içinde input ve output tarafında, default değerler olup olmamasına bağlı olarak iki farklı JSON Schema bile görebilirsiniz.

Bunun nasıl çalıştığına ve gerekirse nasıl değiştirebileceğinize bir bakalım.

Input ve Output için Pydantic Modelleri

Default değerleri olan bir Pydantic modeliniz olduğunu varsayalım; örneğin şöyle:

from fastapi import FastAPI
from pydantic import BaseModel


class Item(BaseModel):
    name: str
    description: str | None = None

# Code below omitted 👇
👀 Full file preview
from fastapi import FastAPI
from pydantic import BaseModel


class Item(BaseModel):
    name: str
    description: str | None = None


app = FastAPI()


@app.post("/items/")
def create_item(item: Item):
    return item


@app.get("/items/")
def read_items() -> list[Item]:
    return [
        Item(
            name="Portal Gun",
            description="Device to travel through the multi-rick-verse",
        ),
        Item(name="Plumbus"),
    ]
🤓 Other versions and variants
from typing import Optional

from fastapi import FastAPI
from pydantic import BaseModel


class Item(BaseModel):
    name: str
    description: Optional[str] = None


app = FastAPI()


@app.post("/items/")
def create_item(item: Item):
    return item


@app.get("/items/")
def read_items() -> list[Item]:
    return [
        Item(
            name="Portal Gun",
            description="Device to travel through the multi-rick-verse",
        ),
        Item(name="Plumbus"),
    ]

Input için Model

Bu modeli şöyle input olarak kullanırsanız:

from fastapi import FastAPI
from pydantic import BaseModel


class Item(BaseModel):
    name: str
    description: str | None = None


app = FastAPI()


@app.post("/items/")
def create_item(item: Item):
    return item

# Code below omitted 👇
👀 Full file preview
from fastapi import FastAPI
from pydantic import BaseModel


class Item(BaseModel):
    name: str
    description: str | None = None


app = FastAPI()


@app.post("/items/")
def create_item(item: Item):
    return item


@app.get("/items/")
def read_items() -> list[Item]:
    return [
        Item(
            name="Portal Gun",
            description="Device to travel through the multi-rick-verse",
        ),
        Item(name="Plumbus"),
    ]
🤓 Other versions and variants
from typing import Optional

from fastapi import FastAPI
from pydantic import BaseModel


class Item(BaseModel):
    name: str
    description: Optional[str] = None


app = FastAPI()


@app.post("/items/")
def create_item(item: Item):
    return item


@app.get("/items/")
def read_items() -> list[Item]:
    return [
        Item(
            name="Portal Gun",
            description="Device to travel through the multi-rick-verse",
        ),
        Item(name="Plumbus"),
    ]

...description alanı zorunlu olmaz. Çünkü None default değerine sahiptir.

Dokümanlarda Input Modeli

Bunu dokümanlarda da doğrulayabilirsiniz; description alanında kırmızı yıldız yoktur, yani required olarak işaretlenmemiştir:

Output için Model

Ancak aynı modeli output olarak şöyle kullanırsanız:

from fastapi import FastAPI
from pydantic import BaseModel


class Item(BaseModel):
    name: str
    description: str | None = None


app = FastAPI()


@app.post("/items/")
def create_item(item: Item):
    return item


@app.get("/items/")
def read_items() -> list[Item]:
    return [
        Item(
            name="Portal Gun",
            description="Device to travel through the multi-rick-verse",
        ),
        Item(name="Plumbus"),
    ]
🤓 Other versions and variants
from typing import Optional

from fastapi import FastAPI
from pydantic import BaseModel


class Item(BaseModel):
    name: str
    description: Optional[str] = None


app = FastAPI()


@app.post("/items/")
def create_item(item: Item):
    return item


@app.get("/items/")
def read_items() -> list[Item]:
    return [
        Item(
            name="Portal Gun",
            description="Device to travel through the multi-rick-verse",
        ),
        Item(name="Plumbus"),
    ]

...description default değere sahip olduğu için, o alan için hiçbir şey döndürmeseniz bile yine de o default değeri alır.

Output Response Verisi için Model

Dokümanlarla etkileşip response'u kontrol ederseniz, kod description alanlarından birine bir şey eklememiş olsa bile, JSON response default değeri (null) içerir:

Bu, alanın her zaman bir değeri olacağı anlamına gelir; sadece bazen bu değer None olabilir (JSON'da null).

Dolayısıyla API'nizi kullanan client'ların bu değerin var olup olmadığını kontrol etmesine gerek yoktur; alanın her zaman mevcut olacağını varsayabilirler, sadece bazı durumlarda default değer olan None gelecektir.

Bunu OpenAPI'de ifade etmenin yolu, bu alanı required olarak işaretlemektir; çünkü her zaman yer alacaktır.

Bu nedenle, bir modelin JSON Schema'sı input mu output mu kullanıldığına göre farklı olabilir:

  • input için description required olmaz
  • output için required olur (ve None olabilir; JSON açısından null)

Dokümanlarda Output Modeli

Dokümanlarda output modelini de kontrol edebilirsiniz; hem name hem de description alanları kırmızı yıldız ile required olarak işaretlenmiştir:

Dokümanlarda Input ve Output Modelleri

OpenAPI içindeki tüm kullanılabilir Schema'lara (JSON Schema'lara) bakarsanız, iki tane olduğunu göreceksiniz: biri Item-Input, diğeri Item-Output.

Item-Input için description required değildir, kırmızı yıldız yoktur.

Ama Item-Output için description required'dır, kırmızı yıldız vardır.

Pydantic v2'nin bu özelliğiyle API dokümantasyonunuz daha hassas olur; ayrıca autogenerated client'lar ve SDK'lar kullanıyorsanız, onlar da daha tutarlı ve daha iyi bir developer experience ile daha doğru üretilir. 🎉

Schema'ları Ayırma

Bazı durumlarda input ve output için aynı schema'yı kullanmak isteyebilirsiniz.

Bunun muhtemelen en yaygın nedeni, halihazırda autogenerated client kodlarınız/SDK'larınızın olması ve henüz bunların hepsini güncellemek istememenizdir. Büyük ihtimalle bir noktada güncellemek isteyeceksiniz, ama belki şu an değil.

Bu durumda FastAPI'de bu özelliği separate_input_output_schemas=False parametresiyle kapatabilirsiniz.

Bilgi

separate_input_output_schemas desteği FastAPI 0.102.0 sürümünde eklendi. 🤓

from fastapi import FastAPI
from pydantic import BaseModel


class Item(BaseModel):
    name: str
    description: str | None = None


app = FastAPI(separate_input_output_schemas=False)


@app.post("/items/")
def create_item(item: Item):
    return item


@app.get("/items/")
def read_items() -> list[Item]:
    return [
        Item(
            name="Portal Gun",
            description="Device to travel through the multi-rick-verse",
        ),
        Item(name="Plumbus"),
    ]
🤓 Other versions and variants
from typing import Optional

from fastapi import FastAPI
from pydantic import BaseModel


class Item(BaseModel):
    name: str
    description: Optional[str] = None


app = FastAPI(separate_input_output_schemas=False)


@app.post("/items/")
def create_item(item: Item):
    return item


@app.get("/items/")
def read_items() -> list[Item]:
    return [
        Item(
            name="Portal Gun",
            description="Device to travel through the multi-rick-verse",
        ),
        Item(name="Plumbus"),
    ]

Dokümanlarda Input ve Output Modelleri için Aynı Schema

Artık model için input ve output tarafında tek bir schema olur: sadece Item. Ayrıca description alanı required değildir: