# Query Parametreleri ve String Doğrulamaları { #query-parameters-and-string-validations } **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 { #additional-validation } `q` opsiyonel olsa bile, verildiği durumda **uzunluğunun 50 karakteri geçmemesini** zorlayacağız. ### `Query` ve `Annotated` import edin { #import-query-and-annotated } Bunu yapmak için önce şunları import edin: * `fastapi` içinden `Query` * `typing` içinden `Annotated` {* ../../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](../deployment/versions.md#upgrading-the-fastapi-versions){.internal-link target=_blank}. /// ## `q` parametresinin tipinde `Annotated` kullanın { #use-annotated-in-the-type-for-the-q-parameter } [Python Types Intro](../python-types.md#type-hints-with-metadata-annotations){.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: ```Python q: str | None = None ``` Şimdi bunu `Annotated` ile saracağız; şöyle olacak: ```Python q: Annotated[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 { #add-query-to-annotated-in-the-q-parameter } 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` { #alternative-old-query-as-the-default-value } 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: ```Python q: str | None = Query(default=None) ``` ...parametreyi `None` varsayılan değeriyle opsiyonel yapar; şununla aynı: ```Python 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`: ```Python 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` { #query-as-the-default-value-or-in-annotated } `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: ```Python 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: ```Python q: Annotated[str, Query()] = "rick" ``` ...veya eski kod tabanlarında şuna rastlarsınız: ```Python q: str = Query(default="rick") ``` ### `Annotated`’ın avantajları { #advantages-of-annotated } 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. `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 { #add-more-validations } `min_length` parametresini de ekleyebilirsiniz: {* ../../docs_src/query_params_str_validations/tutorial003_an_py310.py hl[10] *} ## Regular expression ekleyin { #add-regular-expressions } Parametrenin eşleşmesi gereken bir `pattern` düzenli ifade 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 olarak `fixedquery` değerine sahiptir. * `$`: Orada biter; `fixedquery` sonrası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 { #default-values } 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_py310.py hl[9] *} /// note | Not `None` dahil herhangi bir tipte varsayılan değere sahip olmak, parametreyi opsiyonel (zorunlu değil) yapar. /// ## Zorunlu parametreler { #required-parameters } Daha fazla doğrulama veya metadata tanımlamamız gerekmiyorsa, `q` query parametresini yalnızca varsayılan değer tanımlamayarak zorunlu yapabiliriz: ```Python q: str ``` şunun yerine: ```Python q: str | None = None ``` Acak biz artık `Query` ile tanımlıyoruz; örneğin şöyle: ```Python 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_py310.py hl[9] *} ### Zorunlu ama `None` olabilir { #required-can-be-none } 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 { #query-parameter-list-multiple-values } 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: ```JSON { "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 { #query-parameter-list-multiple-values-with-defaults } Hiç değer verilmezse varsayılan bir `list` de tanımlayabilirsiniz: {* ../../docs_src/query_params_str_validations/tutorial012_an_py310.py hl[9] *} Şu adrese giderseniz: ``` http://localhost:8000/items/ ``` `q`’nun varsayılanı `["foo", "bar"]` olur ve response şöyle olur: ```JSON { "q": [ "foo", "bar" ] } ``` #### Sadece `list` kullanmak { #using-just-list } `list[str]` yerine doğrudan `list` de kullanabilirsiniz: {* ../../docs_src/query_params_str_validations/tutorial013_an_py310.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 { #declare-more-metadata } 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 { #alias-parameters } 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 { #deprecating-parameters } 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 { #exclude-parameters-from-openapi } 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 { #custom-validation } 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 { #understand-that-code } Ö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 { #string-with-value-startswith } 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 { #a-random-item } `data.items()` ile, her dictionary öğesi için key ve value içeren tuple’lardan oluşan bir yinelemeli nesne elde ederiz. Bu yinelemeli nesneyi `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 { #recap } Parametreleriniz için ek doğrulamalar ve metadata tanımlayabilirsiniz. Genel doğrulamalar ve metadata: * `alias` * `title` * `description` * `deprecated` String’lere özel doğrulamalar: * `min_length` * `max_length` * `pattern` `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.