fastapi/docs/tr/docs/tutorial/query-params-str-validation...

474 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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.1e 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:
//// tab | Python 3.10+
```Python
q: str | None = None
```
////
//// tab | Python 3.9+
```Python
q: Union[str, None] = None
```
////
Şimdi bunu `Annotated` ile saracağız; şöyle olacak:
//// tab | Python 3.10+
```Python
q: Annotated[str | None] = None
```
////
//// tab | Python 3.9+
```Python
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 { #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 FastAPIye 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 }
FastAPInin önceki sürümlerinde (<abbr title="before 2023-03 - 2023-03ten önce">0.95.0</abbr> ö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 stringler 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. `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 <a href="https://typer.tiangolo.com/" class="external-link" target="_blank">Typer</a> 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` <abbr title="A regular expression, regex or regexp is a sequence of characters that define a search pattern for strings. - Regular expression (regex/regexp), stringler için arama deseni tanımlayan karakter dizisidir.">regular expression</abbr> tanımlayabilirsiniz:
{* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *}
Bu özel regular expression patterni, 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 expressionlara 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_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 { #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
```
Ancak 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_py39.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, clientları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 URLde `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 URLye 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:
<img src="/img/tutorial/query-params-str-validations/image02.png">
### 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_py39.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_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 { #declare-more-metadata }
Parametre hakkında daha fazla bilgi ekleyebilirsiniz.
Bu bilgiler oluşturulan OpenAPIa 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ı clientlar hâlâ kullandığı için bir süre tutmanız gerekiyor, ama dokümanların bunu açıkça <abbr title="obsolete, recommended not to use it - kullanımdan kalkmış, kullanmamanız önerilir">deprecated</abbr> 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:
<img src="/img/tutorial/query-params-str-validations/image01.png">
## Parametreleri OpenAPIdan 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 <a href="https://docs.pydantic.dev/latest/concepts/validators/#field-after-validator" class="external-link" target="_blank">Pydanticin `AfterValidator`</a>ını kullanarak yapabilirsiniz.
/// tip | İpucu
Pydanticte <a href="https://docs.pydantic.dev/latest/concepts/validators/#field-before-validator" class="external-link" target="_blank">`BeforeValidator`</a> ve başka validatorlar da vardır. 🤓
///
Örneğin bu custom validator, bir item IDsinin <abbr title="ISBN means International Standard Book Number - ISBN, International Standard Book Number (Uluslararası Standart Kitap Numarası) anlamına gelir">ISBN</abbr> kitap numarası için `isbn-` ile veya <abbr title="IMDB (Internet Movie Database) is a website with information about movies - IMDB (Internet Movie Database), filmler hakkında bilgi içeren bir web sitesidir">IMDB</abbr> film URL IDsi 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 validatorlar, requestte 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 tuplelardan oluşan bir <abbr title="Something we can iterate on with a for loop, like a list, set, etc. - for döngüsüyle üzerinde gezebileceğimiz (iterate edebileceğimiz) bir nesne; list, set vb.">iterable object</abbr> elde ederiz.
Bu iterable objecti `list(data.items())` ile düzgün bir `list`e çeviririz.
Ardından `random.choice()` ile listten **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 IDsi vermemiş olsa bile yine de rastgele bir öneri alır.
...bütün bunları **tek bir basit satırda** yapıyoruz. 🤯 Pythonu 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`
Stringlere ö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.