Movatterモバイル変換


[0]ホーム

URL:


Ana içeriğe geç
Join theFastAPI Cloud waiting list 🚀
Follow@fastapi onX (Twitter) to stay updated
FollowFastAPI onLinkedIn to stay updated
Subscribe to theFastAPI and friends newsletter 🎉
sponsor
sponsor
sponsor
sponsor
sponsor
sponsor
sponsor
sponsor
sponsor
sponsor
sponsor

Ek Modeller

🌐 Yapay Zekâ ve İnsanlar Tarafından Çeviri

Bu çeviri, insanlar tarafından yönlendirilen bir yapay zekâ ile oluşturuldu. 🤝

Orijinal anlamın yanlış anlaşılması ya da kulağa doğal gelmeme gibi hatalar içerebilir. 🤖

Yapay zekâ LLM'ini daha iyi yönlendirmemize yardımcı olarak bu çeviriyi iyileştirebilirsiniz.

İngilizce sürüm

Önceki örnekten devam edersek, birbiriyle ilişkili birden fazla modelin olması oldukça yaygındır.

Bu durum özellikle kullanıcı modellerinde sık görülür, çünkü:

  • input modeli birpassword içerebilmelidir.
  • output modelipassword içermemelidir.
  • database modeli büyük ihtimalle hash'lenmiş birpassword tutmalıdır.

Tehlike

Kullanıcının düz metin (plaintext)password'ünü asla saklamayın. Her zaman sonradan doğrulayabileceğiniz "güvenli bir hash" saklayın.

Eğer bilmiyorsanız, "password hash" nedir konusunugüvenlik bölümlerinde öğreneceksiniz.

Birden Çok Model

password alanlarıyla birlikte modellerin genel olarak nasıl görünebileceğine ve nerelerde kullanılacaklarına dair bir fikir:

fromfastapiimportFastAPIfrompydanticimportBaseModel,EmailStrapp=FastAPI()classUserIn(BaseModel):username:strpassword:stremail:EmailStrfull_name:str|None=NoneclassUserOut(BaseModel):username:stremail:EmailStrfull_name:str|None=NoneclassUserInDB(BaseModel):username:strhashed_password:stremail:EmailStrfull_name:str|None=Nonedeffake_password_hasher(raw_password:str):return"supersecret"+raw_passworddeffake_save_user(user_in:UserIn):hashed_password=fake_password_hasher(user_in.password)user_in_db=UserInDB(**user_in.model_dump(),hashed_password=hashed_password)print("User saved! ..not really")returnuser_in_db@app.post("/user/",response_model=UserOut)asyncdefcreate_user(user_in:UserIn):user_saved=fake_save_user(user_in)returnuser_saved

**user_in.model_dump() Hakkında

Pydantic'in.model_dump() Metodu

user_in,UserIn sınıfına ait bir Pydantic modelidir.

Pydantic modellerinde, model verilerini içeren birdict döndüren.model_dump() metodu bulunur.

Yani, şöyle bir Pydantic nesnesiuser_in oluşturursak:

user_in=UserIn(username="john",password="secret",email="john.doe@example.com")

ve sonra şunu çağırırsak:

user_dict=user_in.model_dump()

artıkuser_dict değişkeninde modelin verilerini içeren birdict vardır (Pydantic model nesnesi yerine birdict elde etmiş oluruz).

Ve eğer şunu çağırırsak:

print(user_dict)

şöyle bir Pythondict elde ederiz:

{'username':'john','password':'secret','email':'john.doe@example.com','full_name':None,}

Birdict'i Unpack Etmek

user_dict gibi birdict alıp bunu bir fonksiyona (ya da sınıfa)**user_dict ile gönderirsek, Python bunu "unpack" eder. Yaniuser_dict içindeki key ve value'ları doğrudan key-value argümanları olarak geçirir.

Dolayısıyla, yukarıdakiuser_dict ile devam edersek, şunu yazmak:

UserInDB(**user_dict)

şuna eşdeğer bir sonuç üretir:

UserInDB(username="john",password="secret",email="john.doe@example.com",full_name=None,)

Ya da daha net şekilde,user_dict'i doğrudan kullanarak, gelecekte içeriği ne olursa olsun:

UserInDB(username=user_dict["username"],password=user_dict["password"],email=user_dict["email"],full_name=user_dict["full_name"],)

Bir Pydantic Modelinden Diğerinin İçeriğiyle Pydantic Model Oluşturmak

Yukarıdaki örnekteuser_dict'iuser_in.model_dump() ile elde ettiğimiz için, şu kod:

user_dict=user_in.model_dump()UserInDB(**user_dict)

şuna eşdeğerdir:

UserInDB(**user_in.model_dump())

...çünküuser_in.model_dump() birdict döndürür ve biz de bunuUserInDB'ye** önekiyle vererek Python'ın "unpack" etmesini sağlarız.

Böylece, bir Pydantic modelindeki verilerden başka bir Pydantic model üretmiş oluruz.

Birdict'i Unpack Etmek ve Ek Keyword'ler

Sonrasında, aşağıdaki gibi ek keyword argümanıhashed_password=hashed_password eklemek:

UserInDB(**user_in.model_dump(),hashed_password=hashed_password)

...şuna benzer bir sonuca dönüşür:

UserInDB(username=user_dict["username"],password=user_dict["password"],email=user_dict["email"],full_name=user_dict["full_name"],hashed_password=hashed_password,)

Uyarı

Ek destek fonksiyonları olanfake_password_hasher vefake_save_user sadece verinin olası bir akışını göstermek içindir; elbette gerçek bir güvenlik sağlamazlar.

Tekrarı Azaltma

Kod tekrarını azaltmak,FastAPI'nin temel fikirlerinden biridir.

Kod tekrarı; bug, güvenlik problemi, kodun senkron dışına çıkması (bir yeri güncelleyip diğerlerini güncellememek) gibi sorunların olasılığını artırır.

Bu modellerin hepsi verinin büyük bir kısmını paylaşıyor ve attribute adlarını ve type'larını tekrar ediyor.

Daha iyisini yapabiliriz.

Diğer modellerimiz için temel olacak birUserBase modeli tanımlayabiliriz. Sonra da bu modelden türeyen (subclass) modeller oluşturup onun attribute'larını (type deklarasyonları, doğrulama vb.) miras aldırabiliriz.

Tüm veri dönüştürme, doğrulama, dokümantasyon vb. her zamanki gibi çalışmaya devam eder.

Bu sayede modeller arasındaki farkları (plaintextpassword olan,hashed_password olan vepassword olmayan) sadece o farklılıklar olarak tanımlayabiliriz:

fromfastapiimportFastAPIfrompydanticimportBaseModel,EmailStrapp=FastAPI()classUserBase(BaseModel):username:stremail:EmailStrfull_name:str|None=NoneclassUserIn(UserBase):password:strclassUserOut(UserBase):passclassUserInDB(UserBase):hashed_password:strdeffake_password_hasher(raw_password:str):return"supersecret"+raw_passworddeffake_save_user(user_in:UserIn):hashed_password=fake_password_hasher(user_in.password)user_in_db=UserInDB(**user_in.model_dump(),hashed_password=hashed_password)print("User saved! ..not really")returnuser_in_db@app.post("/user/",response_model=UserOut)asyncdefcreate_user(user_in:UserIn):user_saved=fake_save_user(user_in)returnuser_saved

Union veyaanyOf

Bir response'u iki ya da daha fazla type'ınUnion'ı olarak tanımlayabilirsiniz; bu, response'un bunlardan herhangi biri olabileceği anlamına gelir.

OpenAPI'de buanyOf ile tanımlanır.

Bunu yapmak için standart Python type hint'i olantyping.Union'ı kullanın:

Not

BirUnion tanımlarken en spesifik type'ı önce, daha az spesifik olanı sonra ekleyin. Aşağıdaki örnekte daha spesifik olanPlaneItem,Union[PlaneItem, CarItem] içindeCarItem'dan önce gelir.

fromfastapiimportFastAPIfrompydanticimportBaseModelapp=FastAPI()classBaseItem(BaseModel):description:strtype:strclassCarItem(BaseItem):type:str="car"classPlaneItem(BaseItem):type:str="plane"size:intitems={"item1":{"description":"All my friends drive a low rider","type":"car"},"item2":{"description":"Music is my aeroplane, it's my aeroplane","type":"plane","size":5,},}@app.get("/items/{item_id}",response_model=PlaneItem|CarItem)asyncdefread_item(item_id:str):returnitems[item_id]

Python 3.10'daUnion

Bu örnekteUnion[PlaneItem, CarItem] değeriniresponse_model argümanına veriyoruz.

Bunu birtype annotation içine koymak yerine birargümana değer olarak geçtiğimiz için, Python 3.10'da bileUnion kullanmamız gerekiyor.

Eğer bu bir type annotation içinde olsaydı, dikey çizgiyi kullanabilirdik:

some_variable:PlaneItem|CarItem

Ancak bunuresponse_model=PlaneItem | CarItem atamasına koyarsak hata alırız; çünkü Python bunu bir type annotation olarak yorumlamak yerinePlaneItem ileCarItem arasındageçersiz bir işlem yapmaya çalışır.

Model Listesi

Aynı şekilde, nesne listesi döndüren response'ları da tanımlayabilirsiniz.

Bunun için standart Pythonlist'i kullanın:

fromfastapiimportFastAPIfrompydanticimportBaseModelapp=FastAPI()classItem(BaseModel):name:strdescription:stritems=[{"name":"Foo","description":"There comes my hero"},{"name":"Red","description":"It's my aeroplane"},]@app.get("/items/",response_model=list[Item])asyncdefread_items():returnitems

Rastgeledict ile Response

Bir Pydantic modeli kullanmadan, sadece key ve value type'larını belirterek düz, rastgele birdict ile de response tanımlayabilirsiniz.

Bu, geçerli field/attribute adlarını (Pydantic modeli için gerekli olurdu) önceden bilmiyorsanız kullanışlıdır.

Bu durumdadict kullanabilirsiniz:

fromfastapiimportFastAPIapp=FastAPI()@app.get("/keyword-weights/",response_model=dict[str,float])asyncdefread_keyword_weights():return{"foo":2.3,"bar":3.4}

Özet

Her duruma göre birden fazla Pydantic modeli kullanın ve gerekirse özgürce inheritance uygulayın.

Bir entity'nin farklı "state"lere sahip olması gerekiyorsa, o entity için tek bir veri modeli kullanmak zorunda değilsiniz. Örneğinpassword içeren,password_hash içeren vepassword içermeyen state'lere sahip kullanıcı "entity"si gibi.


[8]ページ先頭

©2009-2026 Movatter.jp