Ana içeriğe geç

Body - Güncellemeler

🌐 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

PUT ile değiştirerek güncelleme

Bir öğeyi güncellemek için HTTP PUT operasyonunu kullanabilirsiniz.

Girdi verisini JSON olarak saklanabilecek bir formata (ör. bir NoSQL veritabanı ile) dönüştürmek için jsonable_encoder kullanabilirsiniz. Örneğin, datetime değerlerini str'ye çevirmek gibi.

from fastapi import FastAPI
from fastapi.encoders import jsonable_encoder
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str | None = None
    description: str | None = None
    price: float | None = None
    tax: float = 10.5
    tags: list[str] = []


items = {
    "foo": {"name": "Foo", "price": 50.2},
    "bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
    "baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
}


@app.get("/items/{item_id}", response_model=Item)
async def read_item(item_id: str):
    return items[item_id]


@app.put("/items/{item_id}", response_model=Item)
async def update_item(item_id: str, item: Item):
    update_item_encoded = jsonable_encoder(item)
    items[item_id] = update_item_encoded
    return update_item_encoded
🤓 Other versions and variants
from typing import Union

from fastapi import FastAPI
from fastapi.encoders import jsonable_encoder
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: Union[str, None] = None
    description: Union[str, None] = None
    price: Union[float, None] = None
    tax: float = 10.5
    tags: list[str] = []


items = {
    "foo": {"name": "Foo", "price": 50.2},
    "bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
    "baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
}


@app.get("/items/{item_id}", response_model=Item)
async def read_item(item_id: str):
    return items[item_id]


@app.put("/items/{item_id}", response_model=Item)
async def update_item(item_id: str, item: Item):
    update_item_encoded = jsonable_encoder(item)
    items[item_id] = update_item_encoded
    return update_item_encoded

PUT, mevcut verinin yerine geçmesi gereken veriyi almak için kullanılır.

Değiştirerek güncelleme uyarısı

Bu, bar öğesini PUT ile, body içinde şu verilerle güncellemek isterseniz:

{
    "name": "Barz",
    "price": 3,
    "description": None,
}

zaten kayıtlı olan "tax": 20.2 alanını içermediği için, input model "tax": 10.5 varsayılan değerini kullanacaktır.

Ve veri, bu "yeni" tax değeri olan 10.5 ile kaydedilecektir.

PATCH ile kısmi güncellemeler

Veriyi kısmen güncellemek için HTTP PATCH operasyonunu da kullanabilirsiniz.

Bu, yalnızca güncellemek istediğiniz veriyi gönderip, geri kalanını olduğu gibi bırakabileceğiniz anlamına gelir.

Not

PATCH, PUT'a göre daha az yaygın kullanılır ve daha az bilinir.

Hatta birçok ekip, kısmi güncellemeler için bile yalnızca PUT kullanır.

Bunları nasıl isterseniz öyle kullanmakta özgürsünüz; FastAPI herhangi bir kısıtlama dayatmaz.

Ancak bu kılavuz, aşağı yukarı, bunların nasıl kullanılması amaçlandığını gösterir.

Pydantic'in exclude_unset parametresini kullanma

Kısmi güncellemeler almak istiyorsanız, Pydantic modelinin .model_dump() metodundaki exclude_unset parametresini kullanmak çok faydalıdır.

Örneğin: item.model_dump(exclude_unset=True).

Bu, item modeli oluşturulurken set edilmiş verileri içeren; varsayılan değerleri hariç tutan bir dict üretir.

Sonrasında bunu, yalnızca set edilmiş (request'te gönderilmiş) veriyi içeren; varsayılan değerleri atlayan bir dict üretmek için kullanabilirsiniz:

from fastapi import FastAPI
from fastapi.encoders import jsonable_encoder
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str | None = None
    description: str | None = None
    price: float | None = None
    tax: float = 10.5
    tags: list[str] = []


items = {
    "foo": {"name": "Foo", "price": 50.2},
    "bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
    "baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
}


@app.get("/items/{item_id}", response_model=Item)
async def read_item(item_id: str):
    return items[item_id]


@app.patch("/items/{item_id}")
async def update_item(item_id: str, item: Item) -> Item:
    stored_item_data = items[item_id]
    stored_item_model = Item(**stored_item_data)
    update_data = item.model_dump(exclude_unset=True)
    updated_item = stored_item_model.model_copy(update=update_data)
    items[item_id] = jsonable_encoder(updated_item)
    return updated_item
🤓 Other versions and variants
from typing import Union

from fastapi import FastAPI
from fastapi.encoders import jsonable_encoder
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: Union[str, None] = None
    description: Union[str, None] = None
    price: Union[float, None] = None
    tax: float = 10.5
    tags: list[str] = []


items = {
    "foo": {"name": "Foo", "price": 50.2},
    "bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
    "baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
}


@app.get("/items/{item_id}", response_model=Item)
async def read_item(item_id: str):
    return items[item_id]


@app.patch("/items/{item_id}")
async def update_item(item_id: str, item: Item) -> Item:
    stored_item_data = items[item_id]
    stored_item_model = Item(**stored_item_data)
    update_data = item.model_dump(exclude_unset=True)
    updated_item = stored_item_model.model_copy(update=update_data)
    items[item_id] = jsonable_encoder(updated_item)
    return updated_item

Pydantic'in update parametresini kullanma

Artık .model_copy() ile mevcut modelin bir kopyasını oluşturup, güncellenecek verileri içeren bir dict ile update parametresini geçebilirsiniz.

Örneğin: stored_item_model.model_copy(update=update_data):

from fastapi import FastAPI
from fastapi.encoders import jsonable_encoder
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str | None = None
    description: str | None = None
    price: float | None = None
    tax: float = 10.5
    tags: list[str] = []


items = {
    "foo": {"name": "Foo", "price": 50.2},
    "bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
    "baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
}


@app.get("/items/{item_id}", response_model=Item)
async def read_item(item_id: str):
    return items[item_id]


@app.patch("/items/{item_id}")
async def update_item(item_id: str, item: Item) -> Item:
    stored_item_data = items[item_id]
    stored_item_model = Item(**stored_item_data)
    update_data = item.model_dump(exclude_unset=True)
    updated_item = stored_item_model.model_copy(update=update_data)
    items[item_id] = jsonable_encoder(updated_item)
    return updated_item
🤓 Other versions and variants
from typing import Union

from fastapi import FastAPI
from fastapi.encoders import jsonable_encoder
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: Union[str, None] = None
    description: Union[str, None] = None
    price: Union[float, None] = None
    tax: float = 10.5
    tags: list[str] = []


items = {
    "foo": {"name": "Foo", "price": 50.2},
    "bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
    "baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
}


@app.get("/items/{item_id}", response_model=Item)
async def read_item(item_id: str):
    return items[item_id]


@app.patch("/items/{item_id}")
async def update_item(item_id: str, item: Item) -> Item:
    stored_item_data = items[item_id]
    stored_item_model = Item(**stored_item_data)
    update_data = item.model_dump(exclude_unset=True)
    updated_item = stored_item_model.model_copy(update=update_data)
    items[item_id] = jsonable_encoder(updated_item)
    return updated_item

Kısmi güncellemeler özeti

Özetle, kısmi güncelleme uygulamak için şunları yaparsınız:

  • (İsteğe bağlı olarak) PUT yerine PATCH kullanın.
  • Kayıtlı veriyi alın.
  • Bu veriyi bir Pydantic modeline koyun.
  • Input modelinden, varsayılan değerler olmadan bir dict üretin (exclude_unset kullanarak).
    • Bu şekilde, modelinizdeki varsayılan değerlerle daha önce saklanmış değerlerin üzerine yazmak yerine, yalnızca kullanıcının gerçekten set ettiği değerleri güncellersiniz.
  • Kayıtlı modelin bir kopyasını oluşturun ve alınan kısmi güncellemeleri kullanarak attribute'larını güncelleyin (update parametresini kullanarak).
  • Kopyalanan modeli DB'nizde saklanabilecek bir şeye dönüştürün (ör. jsonable_encoder kullanarak).
    • Bu, modelin .model_dump() metodunu yeniden kullanmaya benzer; ancak değerlerin JSON'a dönüştürülebilecek veri tiplerine çevrilmesini garanti eder (ör. datetime -> str).
  • Veriyi DB'nize kaydedin.
  • Güncellenmiş modeli döndürün.
from fastapi import FastAPI
from fastapi.encoders import jsonable_encoder
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: str | None = None
    description: str | None = None
    price: float | None = None
    tax: float = 10.5
    tags: list[str] = []


items = {
    "foo": {"name": "Foo", "price": 50.2},
    "bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
    "baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
}


@app.get("/items/{item_id}", response_model=Item)
async def read_item(item_id: str):
    return items[item_id]


@app.patch("/items/{item_id}")
async def update_item(item_id: str, item: Item) -> Item:
    stored_item_data = items[item_id]
    stored_item_model = Item(**stored_item_data)
    update_data = item.model_dump(exclude_unset=True)
    updated_item = stored_item_model.model_copy(update=update_data)
    items[item_id] = jsonable_encoder(updated_item)
    return updated_item
🤓 Other versions and variants
from typing import Union

from fastapi import FastAPI
from fastapi.encoders import jsonable_encoder
from pydantic import BaseModel

app = FastAPI()


class Item(BaseModel):
    name: Union[str, None] = None
    description: Union[str, None] = None
    price: Union[float, None] = None
    tax: float = 10.5
    tags: list[str] = []


items = {
    "foo": {"name": "Foo", "price": 50.2},
    "bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
    "baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
}


@app.get("/items/{item_id}", response_model=Item)
async def read_item(item_id: str):
    return items[item_id]


@app.patch("/items/{item_id}")
async def update_item(item_id: str, item: Item) -> Item:
    stored_item_data = items[item_id]
    stored_item_model = Item(**stored_item_data)
    update_data = item.model_dump(exclude_unset=True)
    updated_item = stored_item_model.model_copy(update=update_data)
    items[item_id] = jsonable_encoder(updated_item)
    return updated_item

İpucu

Aynı tekniği HTTP PUT operasyonu ile de kullanabilirsiniz.

Ancak buradaki örnek PATCH kullanıyor, çünkü bu kullanım senaryoları için tasarlanmıştır.

Not

Input modelin yine de doğrulandığına dikkat edin.

Dolayısıyla, tüm attribute'ların atlanabildiği kısmi güncellemeler almak istiyorsanız, tüm attribute'ları optional olarak işaretlenmiş (varsayılan değerlerle veya None ile) bir modele ihtiyacınız vardır.

Güncelleme için tüm değerleri optional olan modeller ile oluşturma için zorunlu değerlere sahip modelleri ayırmak için, Extra Models bölümünde anlatılan fikirleri kullanabilirsiniz.