18 KiB
Query Parametreleri ve String Doğrulamaları
FastAPI, parametreleriniz için ek bilgi ve doğrulamalar (validation) tanımlamanıza izin verir.
Örnek olarak şu uygulamayı ele alalım:
{* ../../docs_src/query_params_str_validations/tutorial001_py310.py hl[7] *}
Query parametresi q, str | None tipindedir. Yani tipi str’dir ama None da olabilir. Nitekim varsayılan değer None olduğu için FastAPI bunun zorunlu olmadığını anlar.
/// note | Not
FastAPI, q’nun zorunlu olmadığını = None varsayılan değerinden anlar.
str | None kullanmak, editörünüzün daha iyi destek vermesini ve hataları yakalamasını sağlar.
///
Ek doğrulama
q opsiyonel olsa bile, verildiği durumda uzunluğunun 50 karakteri geçmemesini zorlayacağız.
Query ve Annotated import edin
Bunu yapmak için önce şunları import edin:
fastapiiçindenQuerytypingiçindenAnnotated
{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *}
/// info | Bilgi
FastAPI, 0.95.0 sürümünde Annotated desteğini ekledi (ve önermeye başladı).
Daha eski bir sürüm kullanıyorsanız Annotated kullanmaya çalışırken hata alırsınız.
Annotated kullanmadan önce FastAPI sürümünü en az 0.95.1’e yükseltmek için FastAPI sürümünü yükseltin{.internal-link target=_blank}.
///
q parametresinin tipinde Annotated kullanın
Python Types Intro{.internal-link target=_blank} içinde Annotated ile parametrelerinize metadata ekleyebileceğinizi söylemiştim, hatırlıyor musunuz?
Şimdi bunu FastAPI ile kullanmanın zamanı. 🚀
Şu tip anotasyonuna sahiptik:
//// tab | Python 3.10+
q: str | None = None
////
//// tab | Python 3.9+
q: Union[str, None] = None
////
Şimdi bunu Annotated ile saracağız; şöyle olacak:
//// tab | Python 3.10+
q: Annotated[str | None] = None
////
//// tab | Python 3.9+
q: Annotated[Union[str, None]] = None
////
Bu iki sürüm de aynı anlama gelir: q, str veya None olabilen bir parametredir ve varsayılan olarak None’dır.
Şimdi işin eğlenceli kısmına geçelim. 🎉
q parametresindeki Annotated içine Query ekleyin
Artık ek bilgi (bu durumda ek doğrulama) koyabildiğimiz bir Annotated’ımız olduğuna göre, Annotated içine Query ekleyin ve max_length parametresini 50 olarak ayarlayın:
{* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[9] *}
Varsayılan değerin hâlâ None olduğuna dikkat edin; yani parametre hâlâ opsiyonel.
Ama şimdi Annotated içinde Query(max_length=50) kullanarak FastAPI’ye bu değer için ek doğrulama istediğimizi söylüyoruz: en fazla 50 karakter. 😎
/// tip | İpucu
Burada Query() kullanıyoruz çünkü bu bir query parametresi. İleride Path(), Body(), Header() ve Cookie() gibi, Query() ile aynı argümanları kabul eden diğerlerini de göreceğiz.
///
FastAPI artık şunları yapacak:
- Verinin uzunluğunun en fazla 50 karakter olduğundan emin olacak şekilde doğrulayacak
- Veri geçerli değilse client için net bir hata gösterecek
- Parametreyi OpenAPI şemasındaki path operation içinde dokümante edecek (dolayısıyla otomatik dokümantasyon arayüzünde görünecek)
Alternatif (eski): Varsayılan değer olarak Query
FastAPI’nin önceki sürümlerinde (0.95.0 öncesi) Query’yi Annotated içine koymak yerine, parametrenizin varsayılan değeri olarak kullanmanız gerekiyordu. Etrafta bu şekilde yazılmış kod görme ihtimaliniz yüksek; bu yüzden açıklayalım.
/// tip | İpucu
Yeni kodlarda ve mümkün olduğunda, yukarıda anlatıldığı gibi Annotated kullanın. Birden fazla avantajı vardır (aşağıda anlatılıyor) ve dezavantajı yoktur. 🍰
///
Fonksiyon parametresinin varsayılan değeri olarak Query() kullanıp max_length parametresini 50 yapmak şöyle olurdu:
{* ../../docs_src/query_params_str_validations/tutorial002_py310.py hl[7] *}
Bu senaryoda (Annotated kullanmadığımız için) fonksiyondaki None varsayılan değerini Query() ile değiştirmemiz gerekiyor. Bu durumda varsayılan değeri Query(default=None) ile vermeliyiz; bu, (en azından FastAPI açısından) aynı varsayılan değeri tanımlama amacına hizmet eder.
Yani:
q: str | None = Query(default=None)
...parametreyi None varsayılan değeriyle opsiyonel yapar; şununla aynı:
q: str | None = None
Ancak Query sürümü bunun bir query parametresi olduğunu açıkça belirtir.
Sonrasında Query’ye daha fazla parametre geçebiliriz. Bu örnekte string’ler için geçerli olan max_length:
q: str | None = Query(default=None, max_length=50)
Bu, veriyi doğrular, veri geçerli değilse net bir hata gösterir ve parametreyi OpenAPI şemasındaki path operation içinde dokümante eder.
Varsayılan değer olarak Query veya Annotated içinde Query
Annotated içinde Query kullanırken Query için default parametresini kullanamayacağınızı unutmayın.
Bunun yerine fonksiyon parametresinin gerçek varsayılan değerini kullanın. Aksi halde tutarsız olur.
Örneğin şu kullanım izinli değildir:
q: Annotated[str, Query(default="rick")] = "morty"
...çünkü varsayılan değerin "rick" mi "morty" mi olması gerektiği belli değildir.
Bu nedenle (tercihen) şöyle kullanırsınız:
q: Annotated[str, Query()] = "rick"
...veya eski kod tabanlarında şuna rastlarsınız:
q: str = Query(default="rick")
Annotated’ın avantajları
Fonksiyon parametrelerindeki varsayılan değer stiline göre Annotated kullanmanız önerilir; birden fazla nedenle daha iyidir. 🤓
Fonksiyon parametresinin varsayılan değeri, gerçek varsayılan değerdir; bu genel olarak Python açısından daha sezgiseldir. 😌
Aynı fonksiyonu FastAPI olmadan başka yerlerde de çağırabilirsiniz ve beklendiği gibi çalışır. Eğer zorunlu bir parametre varsa (varsayılan değer yoksa) editörünüz hata ile bunu belirtir; ayrıca gerekli parametreyi vermeden çalıştırırsanız Python da şikayet eder.
Annotated kullanmayıp bunun yerine (eski) varsayılan değer stilini kullanırsanız, o fonksiyonu FastAPI olmadan başka yerlerde çağırdığınızda doğru çalışması için argümanları geçmeniz gerektiğini hatırlamak zorunda kalırsınız; yoksa değerler beklediğinizden farklı olur (ör. str yerine QueryInfo veya benzeri). Üstelik editörünüz de şikayet etmez ve Python da fonksiyonu çalıştırırken şikayet etmez; ancak içerideki operasyonlar hata verince ortaya çıkar.
Annotated birden fazla metadata anotasyonu alabildiği için, artık aynı fonksiyonu Typer gibi başka araçlarla da kullanabilirsiniz. 🚀
Daha fazla doğrulama ekleyin
min_length parametresini de ekleyebilirsiniz:
{* ../../docs_src/query_params_str_validations/tutorial003_an_py310.py hl[10] *}
Regular expression ekleyin
Parametrenin eşleşmesi gereken bir pattern regular expression tanımlayabilirsiniz:
{* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *}
Bu özel regular expression pattern’i, gelen parametre değerinin şunları sağladığını kontrol eder:
^: Aşağıdaki karakterlerle başlar; öncesinde karakter yoktur.fixedquery: Tam olarakfixedquerydeğerine sahiptir.$: Orada biter;fixedquerysonrasında başka karakter yoktur.
Bu "regular expression" konuları gözünüzü korkutuyorsa sorun değil. Birçok kişi için zor bir konudur. Regular expression’lara ihtiyaç duymadan da pek çok şey yapabilirsiniz.
Artık ihtiyaç duyduğunuzda FastAPI içinde kullanabileceğinizi biliyorsunuz.
Varsayılan değerler
Elbette None dışında varsayılan değerler de kullanabilirsiniz.
Örneğin q query parametresi için min_length değerini 3 yapmak ve varsayılan değer olarak "fixedquery" vermek istediğinizi düşünelim:
{* ../../docs_src/query_params_str_validations/tutorial005_an_py39.py hl[9] *}
/// note | Not
None dahil herhangi bir tipte varsayılan değere sahip olmak, parametreyi opsiyonel (zorunlu değil) yapar.
///
Zorunlu parametreler
Daha fazla doğrulama veya metadata tanımlamamız gerekmiyorsa, q query parametresini yalnızca varsayılan değer tanımlamayarak zorunlu yapabiliriz:
q: str
şunun yerine:
q: str | None = None
Ancak biz artık Query ile tanımlıyoruz; örneğin şöyle:
q: Annotated[str | None, Query(min_length=3)] = None
Dolayısıyla Query kullanırken bir değeri zorunlu yapmak istediğinizde, varsayılan değer tanımlamamanız yeterlidir:
{* ../../docs_src/query_params_str_validations/tutorial006_an_py39.py hl[9] *}
Zorunlu ama None olabilir
Bir parametrenin None kabul edebileceğini söyleyip yine de zorunlu olmasını sağlayabilirsiniz. Bu, client’ların değer göndermesini zorunlu kılar; değer None olsa bile.
Bunu yapmak için None’ı geçerli bir tip olarak tanımlayın ama varsayılan değer vermeyin:
{* ../../docs_src/query_params_str_validations/tutorial006c_an_py310.py hl[9] *}
Query parametresi listesi / birden fazla değer
Bir query parametresini Query ile açıkça tanımladığınızda, bir değer listesi alacak şekilde (başka bir deyişle, birden fazla değer alacak şekilde) de tanımlayabilirsiniz.
Örneğin URL’de q query parametresinin birden fazla kez görünebilmesini istiyorsanız şöyle yazabilirsiniz:
{* ../../docs_src/query_params_str_validations/tutorial011_an_py310.py hl[9] *}
Sonra şu URL ile:
http://localhost:8000/items/?q=foo&q=bar
path operation function içinde, function parameter olan q parametresinde, birden fazla q query parameters değerini (foo ve bar) bir Python list’i olarak alırsınız.
Dolayısıyla bu URL’ye response şöyle olur:
{
"q": [
"foo",
"bar"
]
}
/// tip | İpucu
Yukarıdaki örnekte olduğu gibi tipi list olan bir query parametresi tanımlamak için Query’yi açıkça kullanmanız gerekir; aksi halde request body olarak yorumlanır.
///
Etkileşimli API dokümanları da buna göre güncellenir ve birden fazla değere izin verir:
Varsayılanlarla query parametresi listesi / birden fazla değer
Hiç değer verilmezse varsayılan bir list de tanımlayabilirsiniz:
{* ../../docs_src/query_params_str_validations/tutorial012_an_py39.py hl[9] *}
Şu adrese giderseniz:
http://localhost:8000/items/
q’nun varsayılanı ["foo", "bar"] olur ve response şöyle olur:
{
"q": [
"foo",
"bar"
]
}
Sadece list kullanmak
list[str] yerine doğrudan list de kullanabilirsiniz:
{* ../../docs_src/query_params_str_validations/tutorial013_an_py39.py hl[9] *}
/// note | Not
Bu durumda FastAPI, listenin içeriğini kontrol etmez.
Örneğin list[int], listenin içeriğinin integer olduğunu kontrol eder (ve dokümante eder). Ancak tek başına list bunu yapmaz.
///
Daha fazla metadata tanımlayın
Parametre hakkında daha fazla bilgi ekleyebilirsiniz.
Bu bilgiler oluşturulan OpenAPI’a dahil edilir ve dokümantasyon arayüzleri ile harici araçlar tarafından kullanılır.
/// note | Not
Farklı araçların OpenAPI desteği farklı seviyelerde olabilir.
Bazıları tanımladığınız ek bilgilerin hepsini göstermeyebilir; ancak çoğu durumda eksik özellik geliştirme planındadır.
///
Bir title ekleyebilirsiniz:
{* ../../docs_src/query_params_str_validations/tutorial007_an_py310.py hl[10] *}
Ve bir description:
{* ../../docs_src/query_params_str_validations/tutorial008_an_py310.py hl[14] *}
Alias parametreleri
Parametrenin adının item-query olmasını istediğinizi düşünün.
Örneğin:
http://127.0.0.1:8000/items/?item-query=foobaritems
Ancak item-query geçerli bir Python değişken adı değildir.
En yakın seçenek item_query olur.
Ama sizin hâlâ tam olarak item-query olmasına ihtiyacınız var...
O zaman bir alias tanımlayabilirsiniz; bu alias, parametre değerini bulmak için kullanılacaktır:
{* ../../docs_src/query_params_str_validations/tutorial009_an_py310.py hl[9] *}
Parametreleri deprecated yapmak
Diyelim ki artık bu parametreyi istemiyorsunuz.
Bazı client’lar hâlâ kullandığı için bir süre tutmanız gerekiyor, ama dokümanların bunu açıkça deprecated olarak göstermesini istiyorsunuz.
O zaman Query’ye deprecated=True parametresini geçin:
{* ../../docs_src/query_params_str_validations/tutorial010_an_py310.py hl[19] *}
Dokümanlarda şöyle görünür:
Parametreleri OpenAPI’dan hariç tutun
Oluşturulan OpenAPI şemasından (dolayısıyla otomatik dokümantasyon sistemlerinden) bir query parametresini hariç tutmak için Query’nin include_in_schema parametresini False yapın:
{* ../../docs_src/query_params_str_validations/tutorial014_an_py310.py hl[10] *}
Özel Doğrulama
Yukarıdaki parametrelerle yapılamayan bazı özel doğrulama ihtiyaçlarınız olabilir.
Bu durumlarda, normal doğrulamadan sonra (ör. değerin str olduğunun doğrulanmasından sonra) uygulanacak bir custom validator function kullanabilirsiniz.
Bunu, Annotated içinde Pydantic’in AfterValidator’ını kullanarak yapabilirsiniz.
/// tip | İpucu
Pydantic’te BeforeValidator ve başka validator’lar da vardır. 🤓
///
Örneğin bu custom validator, bir item ID’sinin ISBN kitap numarası için isbn- ile veya IMDB film URL ID’si için imdb- ile başladığını kontrol eder:
{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py hl[5,16:19,24] *}
/// info | Bilgi
Bu özellik Pydantic 2 ve üzeri sürümlerde mevcuttur. 😎
///
/// tip | İpucu
Veritabanı veya başka bir API gibi herhangi bir harici bileşen ile iletişim gerektiren bir doğrulama yapmanız gerekiyorsa, bunun yerine FastAPI Dependencies kullanmalısınız; onları ileride öğreneceksiniz.
Bu custom validator’lar, request’te sağlanan yalnızca aynı veri ile kontrol edilebilen şeyler içindir.
///
O Kodu Anlamak
Önemli nokta, Annotated içinde bir fonksiyonla birlikte AfterValidator kullanmak. İsterseniz bu kısmı atlayabilirsiniz. 🤸
Ama bu örnek kodun detaylarını merak ediyorsanız, birkaç ek bilgi:
value.startswith() ile String
Fark ettiniz mi? value.startswith() ile bir string, tuple alabilir ve tuple içindeki her değeri kontrol eder:
{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[16:19] hl[17] *}
Rastgele Bir Item
data.items() ile, her dictionary öğesi için key ve value içeren tuple’lardan oluşan bir iterable object elde ederiz.
Bu iterable object’i list(data.items()) ile düzgün bir list’e çeviririz.
Ardından random.choice() ile list’ten rastgele bir değer alırız; yani (id, name) içeren bir tuple elde ederiz. Şuna benzer: ("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy").
Sonra tuple içindeki bu iki değeri id ve name değişkenlerine atarız.
Böylece kullanıcı bir item ID’si vermemiş olsa bile yine de rastgele bir öneri alır.
...bütün bunları tek bir basit satırda yapıyoruz. 🤯 Python’u sevmemek elde mi? 🐍
{* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[22:30] hl[29] *}
Özet
Parametreleriniz için ek doğrulamalar ve metadata tanımlayabilirsiniz.
Genel doğrulamalar ve metadata:
aliastitledescriptiondeprecated
String’lere özel doğrulamalar:
min_lengthmax_lengthpattern
AfterValidator ile custom doğrulamalar.
Bu örneklerde str değerleri için doğrulamanın nasıl tanımlanacağını gördünüz.
Sayılar gibi diğer tipler için doğrulamaları nasıl tanımlayacağınızı öğrenmek için sonraki bölümlere geçin.