Link metni çevrilmelidir, link adresi çeviriye işaret etmelidir:
@ -185,7 +185,7 @@ Link metni çevrilmelidir, link adresi çeviriye işaret etmelidir:
Link'ler çevrilmelidir, ancak adresleri değişmeden kalmalıdır. Bir istisna, FastAPI dokümantasyonunun sayfalarına verilen mutlak link'lerdir. Bu durumda link, çeviriye işaret etmelidir.
`script/translate.py` içindeki genel prompt'ta `### Links` bölümüne bakın.
`scripts/translate.py` içindeki genel prompt'ta `### Links` bölümüne bakın.
////
@ -199,14 +199,9 @@ Burada HTML "abbr" öğeleriyle sarılmış bazı şeyler var (bazıları uydurm
* <abbrtitle="Getting Things Done - İşleri Bitirme">GTD</abbr>
* <abbrtitle="less than - küçüktür"><code>lt</code></abbr>
* <abbrtitle="XML Web Token - XML Web Token">XWT</abbr>
* <abbrtitle="XML Web Token">XWT</abbr>
* <abbrtitle="Parallel Server Gateway Interface - Paralel Sunucu Gateway Interface">PSGI</abbr>
### abbr bir açıklama verir { #the-abbr-gives-an-explanation }
* <abbrtitle="Bir şekilde birbirine bağlanacak ve birlikte çalışacak şekilde yapılandırılmış makinelerden oluşan bir grup.">cluster</abbr>
* <abbrtitle="Girdi ve çıktı katmanları arasında çok sayıda gizli katman içeren yapay sinir ağlarını kullanan; böylece kapsamlı bir iç yapı geliştiren bir machine learning yöntemi">Deep Learning</abbr>
### abbr tam bir ifade ve bir açıklama verir { #the-abbr-gives-a-full-phrase-and-an-explanation }
* <abbrtitle="Mozilla Developer Network - Mozilla Geliştirici Ağı: Firefox ekibi tarafından yazılmış, geliştiricilere yönelik dokümantasyon">MDN</abbr>
@ -220,10 +215,15 @@ Burada HTML "abbr" öğeleriyle sarılmış bazı şeyler var (bazıları uydurm
Çeviriler, LLM'nin kaldırmaması gereken kendi "abbr" öğelerini ekleyebilir. Örneğin İngilizce kelimeleri açıklamak için.
`script/translate.py` içindeki genel prompt'ta `### HTML abbr elements` bölümüne bakın.
`scripts/translate.py` içindeki genel prompt'ta `### HTML abbr elements` bölümüne bakın.
////
## HTML "dfn" öğeleri { #html-dfn-elements }
* <dfntitle="Bir şekilde birbirine bağlanacak ve birlikte çalışacak şekilde yapılandırılmış makinelerden oluşan bir grup.">küme</dfn>
* <dfntitle="Girdi ve çıktı katmanları arasında çok sayıda gizli katman içeren yapay sinir ağlarını kullanan; böylece kapsamlı bir iç yapı geliştiren bir makine öğrenmesi yöntemi">Derin Öğrenme</dfn>
## Başlıklar { #headings }
//// tab | Test
@ -246,7 +246,7 @@ Tekrar merhaba.
Başlıklarla ilgili tek katı kural, LLM'nin süslü parantezler içindeki hash kısmını değiştirmemesidir; böylece link'ler bozulmaz.
`script/translate.py` içindeki genel prompt'ta `### Headings` bölümüne bakın.
`scripts/translate.py` içindeki genel prompt'ta `### Headings` bölümüne bakın.
Dile özel bazı talimatlar için örneğin `docs/de/llm-prompt.md` içindeki `### Headings` bölümüne bakın.
Bu durumda, ek parametreleri ve alt-dependency'leri kontrol etmek için **FastAPI**'nin kullanacağı şey bu `__call__` olacaktır; ayrıca daha sonra *path operation function* içindeki parametreye bir değer geçmek için çağrılacak olan da budur.
@ -26,7 +26,7 @@ Bu durumda, ek parametreleri ve alt-dependency'leri kontrol etmek için **FastAP
Ve şimdi, dependency'yi "parametreleştirmek" için kullanacağımız instance parametrelerini tanımlamak üzere `__init__` kullanabiliriz:
# Gelişmiş Python Tipleri { #advanced-python-types }
Python tipleriyle çalışırken işinize yarayabilecek bazı ek fikirler.
## `Union` veya `Optional` Kullanımı { #using-union-or-optional }
Kodunuz herhangi bir nedenle `|` kullanamıyorsa — örneğin bir tip açıklamasında (type annotation) değil de `response_model=` gibi bir yerdeyse — dikey çizgi (`|`) yerine `typing` içindeki `Union`'ı kullanabilirsiniz.
Örneğin, bir şeyin `str` ya da `None` olabileceğini şöyle belirtebilirsiniz:
```python
from typing import Union
def say_hi(name: Union[str, None]):
print(f"Hi {name}!")
```
`typing`, bir şeyin `None` olabileceğini belirtmek için `Optional` ile bir kısayol da sunar.
Benim oldukça öznel bakış açıma göre küçük bir ipucu:
- 🚨 `Optional[SomeType]` kullanmaktan kaçının
- Bunun yerine ✨ **`Union[SomeType, None]` kullanın** ✨.
İkisi de eşdeğer ve temelde aynıdır; ancak "**optional**" kelimesi değerin isteğe bağlı olduğunu ima eder. Oysa aslında " `None` olabilir" demektir; değer isteğe bağlı olmasa ve hâlâ zorunlu olsa bile.
Bence `Union[SomeType, None]` ne demek istediğini daha açık anlatır.
Burada mesele sadece kelimeler ve isimler. Ancak bu kelimeler sizin ve ekip arkadaşlarınızın koda bakışını etkileyebilir.
Örnek olarak şu fonksiyona bakalım:
```python
from typing import Optional
def say_hi(name: Optional[str]):
print(f"Hey {name}!")
```
`name` parametresi `Optional[str]` olarak tanımlıdır; ancak isteğe bağlı değildir, parametre olmadan fonksiyonu çağıramazsınız:
```Python
say_hi() # Ah hayır, bu hata fırlatır! 😱
```
`name` parametresi varsayılan bir değeri olmadığı için hâlâ zorunludur (yani *optional* değildir). Yine de `name`, değer olarak `None` kabul eder:
```Python
say_hi(name=None) # Bu çalışır, None geçerlidir 🎉
```
İyi haber şu ki, çoğu durumda tip birliklerini (union) tanımlamak için doğrudan `|` kullanabilirsiniz:
```python
def say_hi(name: str | None):
print(f"Hey {name}!")
```
Dolayısıyla, normalde `Optional` ve `Union` gibi isimler için endişelenmenize gerek yok. 😎
Proxy, request'i app server'a (muhtemelen FastAPI CLI üzerinden Uvicorn) iletmeden önce **path prefix**'i anlık olarak **"kırpar"** (strip). Böylece uygulamanız hâlâ `/app` altında servis ediliyormuş gibi davranır ve tüm kodunuzu `/api/v1` prefix'ini içerecek şekilde güncellemeniz gerekmez.
@ -149,14 +149,14 @@ Docs UI'nin, bu API `server`'ının (proxy arkasında) `/api/v1` altında bulund
```JSON hl_lines="4-8"
{
"openapi": "3.1.0",
// More stuff here
// Burada daha fazla şey var
"servers": [
{
"url": "/api/v1"
}
],
"paths": {
// More stuff here
// Burada daha fazla şey var
}
}
```
@ -193,7 +193,7 @@ Uygulamanızın her request için kullandığı mevcut `root_path` değerini ala
Burada sadece göstermek için bunu mesaja dahil ediyoruz.
Alternatif olarak, `--root-path` gibi bir komut satırı seçeneği (veya muadili) sağlayamıyorsanız, FastAPI uygulamanızı oluştururken `root_path` parametresini ayarlayabilirsiniz:
@ -30,7 +30,7 @@ Büyük response'larda, doğrudan bir `Response` döndürmek bir dictionary dön
Ancak döndürdüğünüz içeriğin **JSON ile serialize edilebilir** olduğundan eminseniz, onu doğrudan response class’ına verebilir ve FastAPI’nin response class’ına vermeden önce dönüş içeriğinizi `jsonable_encoder` içinden geçirirken oluşturacağı ek yükten kaçınabilirsiniz.
Bu örnekte `generate_html_response()` fonksiyonu, HTML’i bir `str` olarak döndürmek yerine zaten bir `Response` üretip döndürmektedir.
@ -136,7 +136,7 @@ Bunu doğrudan döndürebilirsiniz.
FastAPI (aslında Starlette) otomatik olarak bir Content-Length header’ı ekler. Ayrıca `media_type`’a göre bir Content-Type header’ı ekler ve text türleri için sona bir charset ekler.
1. Bu generator function’dır. İçinde `yield` ifadeleri olduğu için "generator function" denir.
2. Bir `with` bloğu kullanarak, generator function bittiğinde file-like objenin kapandığından emin oluruz. Yani response göndermeyi bitirdikten sonra kapanır.
@ -255,11 +255,11 @@ Diğer response türlerine göre instantiate ederken farklı argümanlar alır:
File response'ları uygun `Content-Length`, `Last-Modified` ve `ETag` header’larını içerir.
Bu durumda *path operation* function’ınızdan doğrudan dosya path'ini döndürebilirsiniz.
@ -273,7 +273,7 @@ Diyelim ki girintili ve biçimlendirilmiş JSON döndürmek istiyorsunuz; bunun
Bir `CustomORJSONResponse` oluşturabilirsiniz. Burada yapmanız gereken temel şey, content’i `bytes` olarak döndüren bir `Response.render(content)` metodu yazmaktır:
@ -64,7 +64,7 @@ Bu durumda standart `dataclasses` yerine, drop-in replacement olan `pydantic.dat
6. Burada `items` içeren bir dictionary döndürüyoruz; `items` bir dataclass listesi.
FastAPI, veriyi JSON'a <abbrtitle="converting the data to a format that can be transmitted - veriyi aktarılabilir bir formata dönüştürme">serializing</abbr> etmeyi yine başarır.
FastAPI, veriyi JSON'a <dfntitle="veriyi aktarılabilir bir formata dönüştürme">serileştirme</dfn>yi yine başarır.
7. Burada `response_model`, `Author` dataclass'larından oluşan bir listenin type annotation'ını kullanıyor.
Burada, `yield` öncesinde (sahte) model fonksiyonunu machine learning modellerini içeren dictionary’e koyarak, modeli yükleme gibi maliyetli bir *startup* işlemini simüle ediyoruz. Bu kod, *startup* sırasında, uygulama **request almaya başlamadan önce** çalıştırılır.
@ -48,7 +48,7 @@ Belki yeni bir sürüm başlatmanız gerekiyordur, ya da çalıştırmaktan sık
Dikkat edilmesi gereken ilk şey, `yield` içeren async bir fonksiyon tanımlıyor olmamız. Bu, `yield` kullanan Dependencies’e oldukça benzer.
Python’da **context manager**, `with` ifadesi içinde kullanabildiğiniz bir yapıdır. Örneğin `open()` bir context manager olarak kullanılabilir:
@ -82,7 +82,7 @@ Yukarıdaki kod örneğimizde bunu doğrudan kullanmıyoruz; bunun yerine FastAP
`FastAPI` uygulamasının `lifespan` parametresi bir **async context manager** alır; dolayısıyla oluşturduğumuz yeni `lifespan` async context manager’ını buraya geçebiliriz.
Burada `shutdown` event handler fonksiyonu, `log.txt` dosyasına `"Application shutdown"` satırını yazar.
@ -150,11 +150,11 @@ Bu nedenle artık bunun yerine, yukarıda açıklandığı gibi `lifespan` kulla
Meraklı nerd’ler için küçük bir teknik detay. 🤓
Altta, ASGI teknik spesifikasyonunda bu, <ahref="https://asgi.readthedocs.io/en/latest/specs/lifespan.html"class="external-link"target="_blank">Lifespan Protocol</a>’ün bir parçasıdır ve `startup` ile `shutdown` adında event’ler tanımlar.
Altta, ASGI teknik spesifikasyonunda bu, <ahref="https://asgi.readthedocs.io/en/latest/specs/lifespan.html"class="external-link"target="_blank">Lifespan Protokolü</a>’nün bir parçasıdır ve `startup` ile `shutdown` adında event’ler tanımlar.
/// info | Bilgi
Starlette `lifespan` handler’ları hakkında daha fazlasını <ahref="https://www.starlette.dev/lifespan/"class="external-link"target="_blank">Starlette's Lifespan docs</a> içinde okuyabilirsiniz.
Starlette `lifespan` handler’ları hakkında daha fazlasını <ahref="https://www.starlette.dev/lifespan/"class="external-link"target="_blank">Starlette Lifespan dokümanları</a> içinde okuyabilirsiniz.
Ayrıca kodunuzun başka bölgelerinde de kullanılabilecek lifespan state’i nasıl yöneteceğinizi de kapsar.
*Path operation*'ların, request payload ve response payload için kullandıkları modelleri `Item` ve `ResponseMessage` modelleriyle tanımladıklarına dikkat edin.
@ -98,7 +98,7 @@ Birçok durumda FastAPI uygulamanız daha büyük olacaktır ve farklı *path op
Örneğin **items** için bir bölüm, **users** için başka bir bölüm olabilir ve bunları tag'lerle ayırabilirsiniz:
Ana [Tutorial - User Guide](../tutorial/index.md){.internal-link target=_blank} sayfası, **FastAPI**'ın tüm temel özelliklerini tanımanız için yeterli olmalıdır.
Ana [Tutorial - User Guide](../tutorial/index.md){.internal-link target=_blank} sayfası, **FastAPI**'nin tüm temel özelliklerini tanımanız için yeterli olmalıdır.
Sonraki bölümlerde diğer seçenekleri, konfigürasyonları ve ek özellikleri göreceksiniz.
@ -16,6 +16,6 @@ Ve kullanım amacınıza bağlı olarak, çözüm bunlardan birinde olabilir.
## Önce Tutorial'ı Okuyun { #read-the-tutorial-first }
Ana [Tutorial - User Guide](../tutorial/index.md){.internal-link target=_blank} sayfasındaki bilgilerle **FastAPI**'nın çoğu özelliğini yine de kullanabilirsiniz.
Ana [Tutorial - User Guide](../tutorial/index.md){.internal-link target=_blank} sayfasındaki bilgilerle **FastAPI**'nin çoğu özelliğini yine de kullanabilirsiniz.
Ve sonraki bölümler, onu zaten okuduğunuzu ve bu temel fikirleri bildiğinizi varsayar.
@ -32,7 +32,7 @@ Webhook'lar OpenAPI 3.1.0 ve üzeri sürümlerde mevcuttur; FastAPI `0.99.0` ve
Bir **FastAPI** uygulaması oluşturduğunuzda, *webhook*'ları tanımlamak için kullanabileceğiniz bir `webhooks` attribute'u vardır; *path operation* tanımlar gibi, örneğin `@app.webhooks.post()` ile.
@ -40,7 +40,7 @@ Farklı modüllerde (Python dosyalarında) olsalar bile.
Bir *path operation*’ı üretilen OpenAPI şemasından (dolayısıyla otomatik dokümantasyon sistemlerinden) hariç tutmak için `include_in_schema` parametresini kullanın ve `False` yapın:
OpenAPI spesifikasyonunda buna <ahref="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#operation-object"class="external-link"target="_blank">Operation Object</a> denir.
OpenAPI spesifikasyonunda buna <ahref="https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#operation-object"class="external-link"target="_blank">Operation Nesnesi</a> denir.
///
@ -90,9 +90,9 @@ Bir *path operation* için OpenAPI şemasını `openapi_extra` parametresiyle ge
### OpenAPI Extensions { #openapi-extensions }
Örneğin bu `openapi_extra`, [OpenAPI Extensions](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions) tanımlamak için faydalı olabilir:
Örneğin bu `openapi_extra`, [OpenAPI Uzantıları](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions) tanımlamak için faydalı olabilir:
Bu örnekte herhangi bir Pydantic model tanımlamadık. Hatta request body JSON olarak <abbrtitle="converted from some plain format, like bytes, into Python objects - bytes gibi düz bir formattan Python nesnelerine dönüştürme">parsed</abbr> bile edilmiyor; doğrudan `bytes` olarak okunuyor ve `magic_data_reader()` fonksiyonu bunu bir şekilde parse etmekten sorumlu oluyor.
Bu örnekte herhangi bir Pydantic model tanımlamadık. Hatta request body JSON olarak <dfntitle="bytes gibi düz bir formattan, ör. bytes, Python nesnelerine dönüştürme">ayrıştırılmıyor</dfn>; doğrudan `bytes` olarak okunuyor ve `magic_data_reader()` fonksiyonu bunu bir şekilde parse etmekten sorumlu oluyor.
Buna rağmen, request body için beklenen şemayı tanımlayabiliriz.
@ -153,7 +153,7 @@ Ve bunu, request içindeki veri tipi JSON olmasa bile yapabilirsiniz.
Örneğin bu uygulamada, FastAPI’nin Pydantic modellerinden JSON Schema çıkarmaya yönelik entegre işlevselliğini ve JSON için otomatik doğrulamayı kullanmıyoruz. Hatta request content type’ını JSON değil, YAML olarak tanımlıyoruz:
Buna rağmen, varsayılan entegre işlevselliği kullanmasak da, YAML olarak almak istediğimiz veri için JSON Schema’yı manuel üretmek üzere bir Pydantic model kullanmaya devam ediyoruz.
@ -161,7 +161,7 @@ Ardından request’i doğrudan kullanıp body’yi `bytes` olarak çıkarıyoru
Sonrasında kodumuzda bu YAML içeriğini doğrudan parse ediyor, ardından YAML içeriğini doğrulamak için yine aynı Pydantic modeli kullanıyoruz:
**FastAPI** ile bir *path operation* oluşturduğunuzda, normalde ondan herhangi bir veri döndürebilirsiniz: bir `dict`, bir `list`, bir Pydantic model, bir veritabanı modeli vb.
Varsayılan olarak **FastAPI**, döndürdüğünüz bu değeri [JSON Compatible Encoder](../tutorial/encoder.md){.internal-link target=_blank} bölümünde anlatılan `jsonable_encoder` ile otomatik olarak JSON'a çevirir.
Varsayılan olarak **FastAPI**, döndürdüğünüz bu değeri [JSON Uyumlu Encoder](../tutorial/encoder.md){.internal-link target=_blank} bölümünde anlatılan `jsonable_encoder` ile otomatik olarak JSON'a çevirir.
Ardından perde arkasında, JSON-uyumlu bu veriyi (ör. bir `dict`) client'a response göndermek için kullanılacak bir `JSONResponse` içine yerleştirir.
@ -54,12 +54,12 @@ Diyelim ki <a href="https://en.wikipedia.org/wiki/XML" class="external-link" tar
XML içeriğinizi bir string içine koyabilir, onu bir `Response` içine yerleştirip döndürebilirsiniz:
Bir `Response`'u doğrudan döndürdüğünüzde, verisi otomatik olarak validate edilmez, dönüştürülmez (serialize edilmez) veya dokümante edilmez.
Ancak yine de [Additional Responses in OpenAPI](additional-responses.md){.internal-link target=_blank} bölümünde anlatıldığı şekilde dokümante edebilirsiniz.
Ancak yine de [OpenAPI'de Ek Response'lar](additional-responses.md){.internal-link target=_blank} bölümünde anlatıldığı şekilde dokümante edebilirsiniz.
İlerleyen bölümlerde, otomatik veri dönüşümü, dokümantasyon vb. özellikleri korurken bu özel `Response`'ları nasıl kullanıp declare edebileceğinizi göreceksiniz.
Ardından normalde yaptığınız gibi ihtiyacınız olan herhangi bir nesneyi döndürebilirsiniz (bir `dict`, bir veritabanı modeli vb.).
@ -22,7 +22,7 @@ Doğrudan bir `Response` döndürdüğünüzde de header ekleyebilirsiniz.
[Bir Response'u Doğrudan Döndürün](response-directly.md){.internal-link target=_blank} bölümünde anlatıldığı gibi bir response oluşturun ve header'ları ek bir parametre olarak geçin:
URL’yi ilk kez açmaya çalıştığınızda (veya dokümanlardaki "Execute" butonuna tıkladığınızda) tarayıcı sizden kullanıcı adınızı ve şifrenizi ister:
@ -40,13 +40,13 @@ Bunu yönetmek için önce `username` ve `password` değerlerini UTF-8 ile encod
Sonra `secrets.compare_digest()` kullanarak `credentials.username`’in `"stanleyjobson"` ve `credentials.password`’ün `"swordfish"` olduğundan emin olabiliriz.
if not (credentials.username == "stanleyjobson") or not (credentials.password == "swordfish"):
# Return some error
# Bir hata döndür
...
```
@ -104,4 +104,4 @@ Bu sayede uygulama kodunuzda `secrets.compare_digest()` kullanarak bu güvenlik
Credential’ların hatalı olduğunu tespit ettikten sonra, 401 status code ile (credential verilmediğinde dönenle aynı) bir `HTTPException` döndürün ve tarayıcının giriş penceresini yeniden göstermesi için `WWW-Authenticate` header’ını ekleyin:
[Tutorial - User Guide: Security](../../tutorial/security/index.md){.internal-link target=_blank} sayfasında ele alınanların dışında güvenlikle ilgili bazı ek özellikler vardır.
[Öğretici - Kullanıcı Kılavuzu: Güvenlik](../../tutorial/security/index.md){.internal-link target=_blank} sayfasında ele alınanların dışında güvenlikle ilgili bazı ek özellikler vardır.
/// tip | İpucu
@ -14,6 +14,6 @@ Ve kullanım durumunuza göre, çözüm bu bölümlerden birinde olabilir.
## Önce Öğreticiyi Okuyun { #read-the-tutorial-first }
Sonraki bölümler, ana [Tutorial - User Guide: Security](../../tutorial/security/index.md){.internal-link target=_blank} sayfasını zaten okuduğunuzu varsayar.
Sonraki bölümler, ana [Öğretici - Kullanıcı Kılavuzu: Güvenlik](../../tutorial/security/index.md){.internal-link target=_blank} sayfasını zaten okuduğunuzu varsayar.
Hepsi aynı kavramlara dayanır, ancak bazı ek işlevselliklere izin verir.
@ -16,7 +16,7 @@ Bu bölüm az çok ileri seviye sayılır. Yeni başlıyorsanız atlayabilirsini
OAuth2 scope'larına mutlaka ihtiyacınız yok; authentication ve authorization'ı istediğiniz şekilde ele alabilirsiniz.
Ancak scope'lu OAuth2, API'nize (OpenAPI ile) ve API dokümanlarınıza güzel biçimde entegre edilebilir.
Namun scope'lu OAuth2, API'nize (OpenAPI ile) ve API dokümanlarınıza güzel biçimde entegre edilebilir.
Buna rağmen, bu scope'ları (veya başka herhangi bir security/authorization gereksinimini) kodunuzda ihtiyaç duyduğunuz şekilde yine siz zorunlu kılarsınız.
@ -257,7 +257,7 @@ Ancak başkalarının bağlanacağı bir OAuth2 uygulaması geliştiriyorsanız
En yaygını implicit flow'dur.
En güvenlisi code flow'dur; ancak daha fazla adım gerektirdiği için implementasyonu daha karmaşıktır. Daha karmaşık olduğundan, birçok sağlayıcı implicit flow'yu önermeye yönelir.
En güvenlisi code flow'dur; ancak daha fazla adım gerektirdiği için implementasyonu daha karmaşıktır. Daha karmaşıktır olduğundan, birçok sağlayıcı implicit flow'yu önermeye yönelir.
@ -54,7 +54,7 @@ Pydantic model'lerinde olduğu gibi, type annotation'larla (ve gerekirse default
Pydantic model'lerinde kullandığınız aynı doğrulama özelliklerini ve araçlarını burada da kullanabilirsiniz; örneğin farklı veri tipleri ve `Field()` ile ek doğrulamalar.
Sonraki request'lerde dependency'ler içinden `get_settings()` çağrıldığında, `get_settings()`'in iç kodu tekrar çalıştırılıp yeni bir `Settings` nesnesi yaratılmak yerine, ilk çağrıda döndürülen aynı nesne tekrar tekrar döndürülür.
### Otomatik API dokümanlarını kontrol edin { #check-the-automatic-api-docs }
@ -64,4 +64,4 @@ Bu sayede alt uygulama, dokümantasyon arayüzü için o path önekini kullanmas
Ayrıca alt uygulamanın kendi mount edilmiş alt uygulamaları da olabilir; FastAPI tüm bu `root_path`’leri otomatik olarak yönettiği için her şey doğru şekilde çalışır.
`root_path` hakkında daha fazlasını ve bunu açıkça nasıl kullanacağınızı [Behind a Proxy](behind-a-proxy.md){.internal-link target=_blank} bölümünde öğreneceksiniz.
`root_path` hakkında daha fazlasını ve bunu açıkça nasıl kullanacağınızı [Proxy Arkasında](behind-a-proxy.md){.internal-link target=_blank} bölümünde öğreneceksiniz.
* Template döndürecek *path operation* içinde bir `Request` parametresi tanımlayın.
* Oluşturduğunuz `templates` nesnesini kullanarak bir `TemplateResponse` render edip döndürün; template'in adını, request nesnesini ve Jinja2 template'i içinde kullanılacak anahtar-değer çiftlerini içeren bir "context" sözlüğünü (dict) iletin.
@ -46,6 +46,7 @@ Sonrasında override'larınızı (yani kaldırıp sıfırlamayı) `app.dependenc
app.dependency_overrides = {}
```
/// tip | İpucu
Bir dependency'yi yalnızca bazı testler sırasında override etmek istiyorsanız, override'ı testin başında (test function'ının içinde) ayarlayıp testin sonunda (yine test function'ının sonunda) sıfırlayabilirsiniz.
Bu konuda daha fazla ayrıntıyı resmi Starlette dokümantasyon sitesindeki ["Running lifespan in tests in the official Starlette documentation site."](https://www.starlette.dev/lifespan/#running-lifespan-in-tests) bölümünde okuyabilirsiniz.
Bu konuda daha fazla ayrıntıyı resmi Starlette dokümantasyon sitesindeki ["Testlerde lifespan'ı çalıştırma"](https://www.starlette.dev/lifespan/#running-lifespan-in-tests) bölümünde okuyabilirsiniz.
Kullanımdan kaldırılmış `startup` ve `shutdown` event'leri için ise `TestClient`'ı aşağıdaki gibi kullanabilirsiniz:
Tipi `Request` olan bir *path operation function* parameter'ı tanımladığınızda **FastAPI**, o parameter'a `Request` nesnesini geçmesi gerektiğini anlar.
Binary, text ve JSON verisi alıp gönderebilirsiniz.
@ -154,7 +154,7 @@ Bununla WebSocket'e bağlanabilir, ardından mesaj gönderip alabilirsiniz:
Bir WebSocket bağlantısı kapandığında, `await websocket.receive_text()` bir `WebSocketDisconnect` exception'ı raise eder; ardından bunu bu örnekteki gibi yakalayıp (catch) yönetebilirsiniz.
API sistemlerinin ihtiyaç duyduğu temel özelliklerden biri, koddan (Python) veriyi alıp ağ üzerinden gönderilebilecek bir şeye dönüştürmek, yani veri “<abbrtitle="marshalling, conversion olarak da adlandırılır">dönüşüm</abbr>”üdür. Örneğin, bir veritabanından gelen verileri içeren bir objeyi JSON objesine dönüştürmek, `datetime` objelerini string’e çevirmek vb.
API sistemlerinin ihtiyaç duyduğu temel özelliklerden biri, koddan (Python) veriyi alıp ağ üzerinden gönderilebilecek bir şeye dönüştürmek, yani veri “<dfntitle="marshalling, conversion olarak da adlandırılır">dönüşüm</dfn>”üdür. Örneğin, bir veritabanından gelen verileri içeren bir objeyi JSON objesine dönüştürmek, `datetime` objelerini string’e çevirmek vb.
API’ların ihtiyaç duyduğu bir diğer önemli özellik, veri doğrulamadır; belirli parametreler göz önüne alındığında verinin geçerli olduğundan emin olmak. Örneğin, bir alanın `int` olması ve rastgele bir metin olmaması. Bu özellikle dışarıdan gelen veriler için kullanışlıdır.
@ -145,7 +145,7 @@ Bir veri doğrulama sistemi olmadan, tüm bu kontrolleri kod içinde el ile yapm
Marshmallow, bu özellikleri sağlamak için inşa edildi. Harika bir kütüphanedir ve geçmişte çok kullandım.
Ancak Python tip belirteçlerinden önce yazılmıştır. Dolayısıyla her <abbrtitle="verinin nasıl oluşturulması gerektiğinin tanımı">şemayı</abbr> tanımlamak için Marshmallow’un sağladığı belirli yardımcılar ve sınıflar kullanılır.
Ancak Python tip belirteçlerinden önce yazılmıştır. Dolayısıyla her <dfntitle="verinin nasıl oluşturulması gerektiğinin tanımı">şemayı</dfn> tanımlamak için Marshmallow’un sağladığı belirli yardımcılar ve sınıflar kullanılır.
/// check | **FastAPI**'a ilham olan
@ -155,7 +155,7 @@ Kodla, veri tiplerini ve doğrulamayı otomatik sağlayan “şemalar” tanıml
Starlette, yüksek performanslı asyncio servisleri oluşturmak için ideal, hafif bir <abbrtitle="Asenkron Python web uygulamaları geliştirmek için yeni standart">ASGI</abbr> framework’ü/araç takımıdır.
Starlette, yüksek performanslı asyncio servisleri oluşturmak için ideal, hafif bir <dfntitle="Asenkron Python web uygulamaları geliştirmek için yeni standart">ASGI</dfn> framework’ü/araç takımıdır.
Çok basit ve sezgiseldir. Kolayca genişletilebilir ve modüler bileşenlere sahip olacak şekilde tasarlanmıştır.
# Eşzamanlılık ve async / await { #concurrency-and-async-await }
*path operasyon fonksiyonu* için `async def `sözdizimi, asenkron kod, eşzamanlılık ve paralellik hakkında bazı ayrıntılar.
*path operasyon fonksiyonları* için `async def` sözdizimi hakkında detaylar ve asenkron kod, eşzamanlılık (concurrency) ve paralellik üzerine arka plan bilgisi.
<abbrtitle="too long; didn't read - çok uzun; okumadım"><strong>TL;DR:</strong></abbr>
Eğer `await` ile çağrılması gerektiğini belirten üçüncü taraf kütüphaneleri kullanıyorsanız, örneğin:
Eğer `await` ile çağırmanız gerektiğini söyleyen üçüncü taraf kütüphaneler kullanıyorsanız, örneğin:
```Python
results = await some_library()
```
O zaman *path operasyon fonksiyonunu*`async def` ile tanımlayın örneğin:
O zaman *path operasyon fonksiyonlarınızı* aşağıdaki gibi`async def` ile tanımlayın:
```Python hl_lines="2"
@app.get('/')
@ -23,13 +23,13 @@ async def read_results():
/// note | Not
Sadece `async def` ile tanımlanan fonksiyonlar içinde `await` kullanabilirsiniz.
`await` yalnızca `async def` ile oluşturulan fonksiyonların içinde kullanılabilir.
///
---
Eğer bir veritabanı, bir API, dosya sistemi vb. ile iletişim kuran bir üçüncü taraf bir kütüphane kullanıyorsanız ve `await` kullanımını desteklemiyorsa, (bu şu anda çoğu veritabanı kütüphanesi için geçerli bir durumdur), o zaman *path operasyon fonksiyonunuzu*`def` kullanarak normal bir şekilde tanımlayın, örneğin:
Eğer bir veritabanı, bir API, dosya sistemi vb. ile iletişim kuran ve `await` desteği olmayan bir üçüncü taraf kütüphane kullanıyorsanız (bu şu anda çoğu veritabanı kütüphanesi için geçerlidir), o zaman *path operasyon fonksiyonlarınızı* normal olarak `def` ile tanımlayın:
```Python hl_lines="2"
@app.get('/')
@ -40,279 +40,307 @@ def results():
---
Eğer uygulamanız (bir şekilde) başka bir şeyle iletişim kurmak ve onun cevap vermesini beklemek zorunda değilse,`async def` kullanın.
Uygulamanız (bir şekilde) başka bir şeyle iletişim kurmak ve onun yanıtını beklemek zorunda değilse, içinde `await` kullanmanız gerekmese bile`async def` kullanın.
---
Sadece bilmiyorsanız, normal `def` kullanın.
Emin değilseniz, normal `def` kullanın.
---
**Not**: *path operasyon fonksiyonlarınızda*`def` ve `async def`'i ihtiyaç duyduğunuz gibi karıştırabilir ve her birini sizin için en iyi seçeneği kullanarak tanımlayabilirsiniz. FastAPI onlarla doğru olanı yapacaktır.
Not: *path operasyon fonksiyonlarınızda*`def` ve `async def`'i ihtiyacınız kadar karıştırabilirsiniz, her birini sizin için en iyi seçenekle tanımlayın. FastAPI onlar için doğru olanı yapacaktır.
Her neyse, yukarıdaki durumlardan herhangi birinde, FastAPI yine de asenkron olarak çalışacak ve son derece hızlı olacaktır.
Yukarıdaki durumların herhangi birinde FastAPI yine de asenkron olarak çalışır ve son derece hızlıdır.
Ancak yukarıdaki adımları takip ederek, bazı performans optimizasyonları yapılabilecektir.
Ancak yukarıdaki adımları izleyerek bazı performans optimizasyonları mümkün olur.
## Teknik Detaylar
## Teknik Detaylar { #technical-details }
Python'un modern versiyonlarında**`async` ve `await`** sözdizimi ile **"coroutines"** kullanan**"asenkron kod"** desteğine sahiptir.
Python’un modern sürümleri,**`async` ve `await`** sözdizimiyle, **"coroutines"** denilen bir yapıyı kullanarak**"asenkron kod"** desteğine sahiptir.
Bu ifadeyi aşağıdaki bölümlerde daha da ayrıntılı açıklayalım:
Aşağıdaki bölümlerde bu ifadeyi parça parça ele alalım:
* **Asenkron kod**
* **Asenkron Kod**
* **`async` ve `await`**
* **Coroutines**
* **Coroutine'ler**
## Asenkron kod
## Asenkron Kod { #asynchronous-code }
Asenkron kod programlama dilinin 💬 bilgisayara / programa 🤖 kodun bir noktasında, *başka bir kodun* bir yerde bitmesini 🤖 beklemesi gerektiğini söylemenin bir yoludur. Bu *başka koda* "slow-file" denir 📝.
Asenkron kod, dilin 💬 bilgisayara / programa 🤖 kodun bir noktasında, bir yerde *başka bir şeyin* bitmesini beklemesi gerektiğini söylemesinin bir yoludur. Diyelim ki bu *başka şeye* "slow-file" 📝 diyoruz.
Böylece, bu süreçte bilgisayar "slow-file" 📝 tamamlanırken gidip başka işler yapabilir.
Bu sırada bilgisayar, "slow-file" 📝 biterken gidip başka işler yapabilir.
Sonra bilgisayar / program 🤖 her fırsatı olduğunda o noktada yaptığı tüm işleri 🤖 bitirene kadar geri dönücek. Ve 🤖 yapması gerekeni yaparak, beklediği görevlerden herhangi birinin bitip bitmediğini görecek.
Sonra bilgisayar / program 🤖, ya tekrar beklediği için ya da o anda elindeki tüm işleri bitirdiğinde fırsat buldukça geri gelir. Ve beklediği görevlerden herhangi biri bittiyse, yapılması gerekenleri yapar.
Ardından, 🤖 bitirmek için ilk görevi alır ("slow-file" 📝) ve onunla ne yapması gerekiyorsa onu devam ettirir.
Ardından, 🤖 ilk biten görevi alır (örneğin bizim "slow-file" 📝) ve onunla yapması gerekenlere devam eder.
Bu "başka bir şey için bekle" normalde, aşağıdakileri beklemek gibi (işlemcinin ve RAM belleğinin hızına kıyasla) nispeten "yavaş" olan <abbrtitle="Input ve Output (Giriş ve Çıkış)">I/O</abbr> işlemlerine atıfta bulunur:
Bu "başka bir şeyi beklemek" genelde işlemci ve RAM hızına kıyasla nispeten "yavaş" olan <abbrtitle="Input and Output - Giriş ve Çıkış">I/O</abbr> işlemlerine atıfta bulunur, örneğin şunları beklemek gibi:
* istemci tarafından ağ üzerinden veri göndermek
* ağ üzerinden istemciye gönderilen veriler
* sistem tarafından okunacak ve programınıza verilecek bir dosya içeriği
* programınızın diske yazılmak üzere sisteme verdiği dosya içerikleri
* istemciden verinin ağ üzerinden gelmesi
* programınızın gönderdiği verinin ağ üzerinden istemciye ulaşması
* diskteki bir dosyanın içeriğinin sistem tarafından okunup programınıza verilmesi
* programınızın sisteme verdiği içeriğin diske yazılması
* uzak bir API işlemi
* bir veritabanı bitirme işlemi
* sonuçları döndürmek için bir veritabanı sorgusu
* bir veritabanı işleminin bitmesi
* bir veritabanı sorgusunun sonuç döndürmesi
* vb.
Yürütme süresi çoğunlukla <abbrtitle="Input ve Output (Giriş ve Çıkış)">I/O</abbr> işlemleri beklenerek tüketildiğinden bunlara "I/O bağlantılı" işlemler denir.
Çalışma süresi çoğunlukla<abbrtitle="Input and Output - Giriş ve Çıkış">I/O</abbr> işlemlerini beklemekle geçtiğinden, bunlara "I/O bound" işlemler denir.
Buna "asenkron" denir, çünkü bilgisayar/program yavaş görevle "senkronize" olmak zorunda değildir, görevin tam olarak biteceği anı bekler, hiçbir şey yapmadan, görev sonucunu alabilmek ve çalışmaya devam edebilmek için .
"Bunun" asenkron" denmesinin sebebi, bilgisayarın / programın yavaş görevle "senkronize" olmak, görev tam bittiği anda orada olup görev sonucunu almak ve işe devam etmek için hiçbir şey yapmadan beklemek zorunda olmamasıdır.
Bunun yerine, "asenkron" bir sistem olarak, bir kez bittiğinde, bilgisayarın / programın yapması gerekeni bitirmesi için biraz (birkaç mikrosaniye) sırada bekleyebilir ve ardından sonuçları almak için geri gelebilir ve onlarla çalışmaya devam edebilir.
Bunun yerine "asenkron" bir sistem olarak, görev bittiğinde, bilgisayarın / programın o sırada yaptığı işi bitirmesi için biraz (birkaç mikrosaniye) sırada bekleyebilir ve sonra sonuçları almak üzere geri dönüp onlarla çalışmaya devam edebilir.
"Senkron" ("asenkron"un aksine) için genellikle "sıralı" terimini de kullanırlar, çünkü bilgisayar/program, bu adımlar beklemeyi içerse bile, farklı bir göreve geçmeden önce tüm adımları sırayla izler.
"Senkron" (asenkronun tersi) için genelde "sıralı" terimi de kullanılır; çünkü bilgisayar / program, farklı bir göreve geçmeden önce tüm adımları sırayla izler, bu adımlar beklemeyi içerse bile.
### Eşzamanlılık ve Burgerler { #concurrency-and-burgers }
### Eşzamanlılık (Concurrency) ve Burgerler
Yukarıda anlatılan **asenkron** kod fikrine bazen **"eşzamanlılık"** (concurrency) da denir. **"Paralellik"**ten (parallelism) farklıdır.
**Eşzamanlılık** ve **paralellik**, "aynı anda az çok birden fazla şeyin olması" ile ilgilidir.
Yukarıda açıklanan bu **asenkron** kod fikrine bazen **"eşzamanlılık"** da denir. **"Paralellikten"** farklıdır.
Ama *eşzamanlılık* ve *paralellik* arasındaki ayrıntılar oldukça farklıdır.
**Eşzamanlılık** ve **paralellik**, "aynı anda az ya da çok olan farklı işler" ile ilgilidir.
Farkı görmek için burgerlerle ilgili şu hikayeyi hayal edin:
Ancak *eşzamanlılık* ve *paralellik* arasındaki ayrıntılar oldukça farklıdır.
### Eşzamanlı Burgerler { #concurrent-burgers }
Aşkınla fast food almaya gidiyorsun, kasiyer senden önceki insanların siparişlerini alırken sıraya giriyorsun. 😍
Farkı görmek için burgerlerle ilgili aşağıdaki hikayeyi hayal edin:
Sonra sıra size geliyor, sen ve aşkın için 2 çok havalı burger sipariş ediyorsun. 🍔🍔
<!-- Cinsiyetten bağımsız olan aşçı emojisi "🧑🍳" tarayıcılarda yeterince iyi görüntülenmiyor. Bu yüzden erken "👨🍳" ve kadın "👩🍳" aşçıları karışık bir şekilde kullanıcağım. -->
Kasiyer 💁 mutfakdaki aşçıya 👨🍳 hamburgerleri 🍔 hazırlaması gerektiğini söyler ve aşçı bunu bilir (o an önceki müşterilerin siparişlerini hazırlıyor olsa bile).
Bu hikayedeki bilgisayar / program 🤖 olduğunuzu hayal edin.
Bu hikâyede bilgisayar / program 🤖 olduğunu hayal et.
Sırada beklerken boştasın 😴, sıranı beklerken herhangi bir "üretim" yapmıyorsun. Ama bu sıra hızlı çünkü kasiyer sadece siparişleri alıyor (onları hazırlamıyor), burada bir sıknıtı yok.
Sıradayken sadece boştasın 😴, sıranı bekliyorsun, çok "üretken" bir şey yapmıyorsun. Ama sorun yok, çünkü kasiyer sadece sipariş alıyor (hazırlamıyor), bu yüzden sıra hızlı ilerliyor.
Sonra sıra size geldiğinde gerçekten "üretken" işler yapabilirsiniz 🤓, menüyü oku, ne istediğine larar ver, aşkının seçimini al 😍, öde 💸, doğru kartı çıkart, ödemeyi kontrol et, faturayı kontrol et, siparişin doğru olup olmadığını kontrol et, vb.
Sıra sana geldiğinde gerçekten "üretken" işler yapıyorsun: menüyü işliyorsun, ne istediğine karar veriyorsun, aşkının seçimini alıyorsun, ödüyorsun, doğru para ya da kartı verdiğini kontrol ediyorsun, doğru ücretlendirildiğini kontrol ediyorsun, sipariş kalemlerinin doğru olduğunu kontrol ediyorsun, vb.
Ama hamburgerler 🍔 hazır olmamasına rağmen Kasiyer 💁 ile işiniz "duraklıyor" ⏸, çünkü hamburgerlerin hazır olmasını bekliyoruz 🕙.
Ama sonra, burgerlerin hâlâ gelmemiş olsa da, kasiyerle olan işin "duraklatılıyor" ⏸, çünkü burgerlerin hazır olmasını 🕙 beklemen gerekiyor.
Ama tezgahtan uzaklaşıp sıranız gelene kadarmasanıza dönebilir 🔀 ve dikkatinizi aşkınıza 😍 verebilirsiniz vr bunun üzerine "çalışabilirsiniz" ⏯ 🤓. Artık "üretken" birşey yapıyorsunuz 🤓, sevgilinle 😍 flört eder gibi.
Fakat tezgâhtan uzaklaşıp masada sıra numaranla oturduğun için, dikkatinizi 🔀 aşkına çevirebilir, onunla "çalışmaya" ⏯ 🤓 odaklanabilirsin. Yani yine çok "üretken" bir şey yapıyorsun, aşkınla flört etmek gibi 😍.
Kasiyer 💁 "Hamburgerler hazır !" 🍔 dediğinde ve görüntülenen numara sizin numaranız olduğunda hemen koşup hamburgerlerinizi almaya çalışmıyorsunuz. Biliyorsunuzki kimse sizin hamburgerlerinizi 🍔 çalmayacak çünkü sıra sizin.
Ardından kasiyer 💁, tezgâh ekranına numaranı koyarak "burgerleri bitirdim" diyor; ama numara seninki olduğunda çılgınca sıçramıyorsun. Sıra numaran sende, herkesin kendi numarası var; kimse burgerlerini çalamaz.
Yani Aşkınızın😍 hikayeyi bitirmesini bekliyorsunuz (çalışmayı bitir ⏯ / görev işleniyor.. 🤓), nazikçe gülümseyin ve hamburger yemeye gittiğinizi söyleyin ⏸.
Bu yüzden aşkının hikâyeyi bitirmesini (mevcut işi ⏯ / işlenen görevi 🤓 bitirmesini) bekliyor, nazikçe gülümsüyor ve burgerleri almaya gittiğini söylüyorsun ⏸.
Ardından tezgaha 🔀, şimdi biten ilk göreve ⏯ gidin, Hamburgerleri 🍔 alın, teşekkür edin ve masaya götürün. sayacın bu adımı tamamlanır ⏹. Bu da yeni bir görev olan "hamburgerleri ye" 🔀 ⏯ görevini başlatırken "hamburgerleri al" ⏹ görevini bitirir.
Sonra tezgâha 🔀 gidip artık bitmiş olan ilk göreve ⏯ dönüyor, burgerleri alıyor, teşekkür ediyor ve masaya getiriyorsun. Tezgâhla etkileşimin bu adımı / görevi böylece bitiyor ⏹. Bu da yeni bir görev olan "burgerleri yemek" 🔀 ⏯ görevini oluşturuyor, ama "burgerleri almak" görevi tamamlandı ⏹.
### Parallel Hamburgerler
### Paralel Burgerler { #parallel-burgers }
Şimdi bunların "Eşzamanlı Hamburger" değil, "Paralel Hamburger" olduğunu düşünelim.
Şimdi bunların "Eşzamanlı Burgerler" değil, "Paralel Burgerler" olduğunu hayal edelim.
Hamburger 🍔 almak için 😍 aşkınla Paralel fast food'a gidiyorsun.
Aşkınla paralel fast food almaya gidiyorsun.
Birden fazla kasiyer varken (varsayalım 8) sıraya girdiniz👩🍳👨🍳👩🍳👨🍳👩🍳👨🍳👩🍳👨🍳 ve sıranız gelene kadar bekliyorsunuz.
Aynı anda aşçı da olan birden fazla (8 diyelim) kasiyerin, senden önceki insanların siparişlerini aldığı bir sırada bekliyorsun.
Sizden önceki herkez ayrılmadan önce hamburgerlerinin 🍔 hazır olmasını bekliyor 🕙. Çünkü kasiyerlerin her biri bir hamburger hazırlanmadan önce bir sonraki siparişe geçmiiyor.
Senden önceki herkes, tezgâhtan ayrılmadan önce burgerlerinin hazırlanmasını bekliyor; çünkü 8 kasiyerin her biri bir sonraki siparişe geçmeden önce burgeri hemen gidip hazırlıyor.
Sonunda senin sıran, aşkın 😍 ve kendin için 2 hamburger 🍔 siparişi verdiniz.
Sen ve aşkın 😍 sıranızı korumak ve hamburgerleri almakla o kadar meşgulsünüz ki birbirinize vakit 🕙 ayıramıyorsunuz 😞.
Kasiyer mutfağa gidiyor.
İşte bu "senkron" çalışmadır. Kasiyer/aşçı 👨🍳ile senkron hareket ediyorsunuz. Bu yüzden beklemek 🕙 ve kasiyer/aşçı burgeri 🍔bitirip size getirdiğinde orda olmak zorundasınız yoksa başka biri alabilir.
Tezgâhın önünde ayakta 🕙 bekliyorsun; sıra numarası olmadığından, burgerlerini senden önce kimsenin almaması için orada durman gerekiyor.
Sonra kasiyeri/aşçı 👨🍳 nihayet hamburgerlerinizle 🍔, uzun bir süre sonra 🕙 tezgaha geri geliyor.
Burgerlerinizi 🍔 al ve aşkınla masanıza doğru ilerle 😍.
Sen ve aşkın, kimsenin önünüze geçip burgerler gelince almaması için meşgul olduğunuzdan, aşkına dikkatini veremiyorsun. 😞
Sadece burgerini yiyorsun 🍔 ve bitti ⏹.
Bu "senkron" bir iştir; kasiyer/aşçı 👨🍳 ile "senkronize"sin. 🕙 Beklemen ve kasiyer/aşçı 👨🍳 burgerleri bitirip sana verdiği anda tam orada olman gerekir; yoksa bir başkası alabilir.
Bekleyerek çok fazla zaman geçtiğinden 🕙 konuşmaya çok fazla vakit kalmadı 😞.
Paralel burger senaryosunda ise, siz iki işlemcili birer robotsunuz 🤖 (sen ve sevgilin 😍), Beklıyorsunuz 🕙 hem konuşarak güzel vakit geçirirken ⏯ hem de sıranızı bekliyorsunuz 🕙.
Mağazada ise 8 işlemci bulunuyor (Kasiyer/aşçı) 👩🍳👨🍳👩🍳👨🍳👩🍳👨🍳👩🍳👨🍳. Eşzamanlı burgerde yalnızca 2 kişi olabiliyordu (bir kasiyer ve bir aşçı) 💁 👨🍳.
Vaktin çoğu tezgâhın önünde 🕙 beklemekle geçtiğinden, pek konuşma ya da flört olmadı. 😞
Bu paralel burger senaryosunda, ikiniz (sen ve aşkın) iki işlemcili bir bilgisayar / programsınız 🤖; ikiniz de uzun süre tezgâhta "bekleme" işine 🕙 dikkat ⏯ ayırıyorsunuz.
Fast food dükkânında 8 işlemci var (kasiyer/aşçılar). Eşzamanlı burger dükkânında yalnızca 2 kişi olabilir (bir kasiyer ve bir aşçı).
Ama yine de nihai deneyim pek iyi değil. 😞
Bir gerçek hayat örneği verelim. Bir banka hayal edin.
---
Bankaların çoğunda birkaç kasiyer 👨💼👨💼👨💼👨💼 ve uzun bir sıra var 🕙🕙🕙🕙🕙🕙🕙🕙.
Bu, burgerler için paralel karşılık gelen hikâye olurdu. 🍔
Tüm işi sırayla bir müşteri ile yapan tüm kasiyerler 👨💼⏯.
Daha "gerçek hayat" bir örnek için, bir banka hayal edin.
Ve uzun süre kuyrukta beklemek 🕙 zorundasın yoksa sıranı kaybedersin.
Yakın zamana kadar, bankaların çoğunda birden çok gişe memuru 👨💼👨💼👨💼👨💼 ve uzun bir sıra 🕙🕙🕙🕙🕙🕙🕙🕙 vardı.
Muhtemelen ayak işlerı yaparken sevgilini 😍 bankaya 🏦 getirmezsin.
Tüm gişe memurları bir müşteriyle tüm işi yapar, sonra sıradakiyle 👨💼⏯.
### Burger Sonucu
Ve sıranı kaybetmemek için uzun süre 🕙 kuyrukta beklemen gerekir.
Bu "aşkınla fast food burgerleri" senaryosunda, çok fazla bekleme olduğu için 🕙, eşzamanlı bir sisteme sahip olmak çok daha mantıklı ⏸🔀⏯.
Muhtemelen, bankada 🏦 işlerini hallederken aşkını 😍 yanında götürmek istemezsin.
Web uygulamalarının çoğu için durum böyledir.
### Burger Sonucu { #burger-conclusion }
Pek çok kullanıcı var, ama sunucunuz pek de iyi olmayan bir bağlantı ile istek atmalarını bekliyor.
"Fast food burgerleri ve aşkın" senaryosunda, çok fazla bekleme 🕙 olduğundan, eşzamanlı bir sistem ⏸🔀⏯ çok daha mantıklıdır.
Ve sonra yanıtların geri gelmesi için tekrar 🕙 bekliyor
Bu, çoğu web uygulaması için de geçerlidir.
Bu "bekleme" 🕙 mikrosaniye cinsinden ölçülür, yine de, hepsini toplarsak çok fazla bekleme var.
Çok fazla kullanıcı vardır; ancak sunucunuz, iyi olmayan bağlantılarından gelen istekleri 🕙 bekler.
Bu nedenle, web API'leri için asenkron ⏸🔀⏯ kod kullanmak çok daha mantıklı.
Ve sonra yanıtların geri gelmesini yine 🕙 bekler.
Mevcut popüler Python frameworklerinin çoğu (Flask ve Django gibi), Python'daki yeni asenkron özellikler mevcut olmadan önce yazıldı. Bu nedenle, dağıtılma biçimleri paralel yürütmeyi ve yenisi kadar güçlü olmayan eski bir eşzamansız yürütme biçimini destekler.
Bu "beklemeler" 🕙 mikrosaniyelerle ölçülür; ama hepsi toplandığında sonuçta oldukça fazla bekleme olur.
Asenkron web (ASGI) özelliği, WebSockets için destek eklemek için Django'ya eklenmiş olsa da.
Bu yüzden web API’leri için asenkron ⏸🔀⏯ kod kullanmak çok mantıklıdır.
Asenkron çalışabilme NodeJS in popüler olmasının sebebi (paralel olamasa bile) ve Go dilini güçlü yapan özelliktir.
Bu tür asenkronluk, NodeJS’i popüler yapan şeydir (NodeJS paralel olmasa bile) ve Go dilinin gücüdür.
Ve bu **FastAPI** ile elde ettiğiniz performans düzeyiyle aynıdır.
Ve **FastAPI** ile elde ettiğiniz performans seviyesi de budur.
Aynı anda paralellik ve asenkronluğa sahip olabildiğiniz için, test edilen NodeJS çerçevelerinin çoğundan daha yüksek performans elde edersiniz ve C'ye daha yakın derlenmiş bir dil olan Go ile eşit bir performans elde edersiniz <ahref="https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1"class="external-link"target="_blank">(bütün teşekkürler Starlette'e )</a>.
Ayrıca, aynı anda hem paralellik hem de asenkronluk kullanabildiğiniz için, test edilen çoğu NodeJS framework’ünden daha yüksek ve C’ye daha yakın derlenen bir dil olan Go ile başa baş performans elde edersiniz <ahref="https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1"class="external-link"target="_blank">(hepsi Starlette sayesinde)</a>.
### Eşzamanlılık paralellikten daha mı iyi?
### Eşzamanlılık paralellikten daha mı iyi? { #is-concurrency-better-than-parallelism }
Hayır! Hikayenin ahlakı bu değil.
Hayır! Hikâyenin özü bu değil.
Eşzamanlılık paralellikten farklıdır. Ve çok fazla bekleme içeren **belirli** senaryolarda daha iyidir. Bu nedenle, genellikle web uygulamaları için paralellikten çok daha iyidir. Ama her şey için değil.
Eşzamanlılık paralellikten farklıdır. Ve çok fazla bekleme içeren **belirli** senaryolarda daha iyidir. Bu nedenle, genellikle web uygulaması geliştirme için paralellikten çok daha iyidir. Ama her şey için değil.
Yanı, bunu aklınızda oturtmak için aşağıdaki kısa hikayeyi hayal edin:
Bunu dengelemek için, şu kısa hikâyeyi hayal edin:
> Büyük, kirli bir evi temizlemelisin.
> Büyük, kirli bir evi temizlemen gerekiyor.
*Evet, tüm hikaye bu*.
*Evet, tüm hikâye bu kadar*.
---
Beklemek yok 🕙. Hiçbir yerde. Sadece evin birden fazla yerinde yapılacak fazlasıyla iş var.
Hiçbir yerde 🕙 bekleme yok; sadece evin birden fazla yerinde yapılacak çok iş var.
You could have turns as in the burgers example, first the living room, then the kitchen, but as you are not waiting 🕙 for anything, just cleaning and cleaning, the turns wouldn't affect anything.
Hamburger örneğindeki gibi dönüşleriniz olabilir, önce oturma odası, sonra mutfak, ama hiçbir şey için 🕙 beklemediğinizden, sadece temizlik, temizlik ve temizlik, dönüşler hiçbir şeyi etkilemez.
Hamburger örneğindeki gibi dönüşlerle ilerleyebilirsin, önce salon, sonra mutfak; ama hiçbir şey 🕙 beklemediğin için, sadece temizlik yaptığından, dönüşlerin hiçbir etkisi olmaz.
Sıralı veya sırasız (eşzamanlılık) bitirmek aynı zaman alır ve aynı miktarda işi yaparsınız.
Dönüşlerle ya da dönüşsüz (eşzamanlılık) bitirmek aynı zaman alır ve aynı miktarda iş yapmış olursun.
Ama bu durumda, 8 eski kasiyer/aşçı - yeni temizlikçiyi getirebilseydiniz 👩🍳👨🍳👩🍳👨🍳👩🍳👨🍳👩🍳👨🍳 ve her birini (artı siz) evin bir bölgesini temizlemek için görevlendirseydiniz, ekstra yardımla tüm işleri **paralel** olarak yapabilir ve çok daha erken bitirebilirdiniz.
Ama bu durumda, 8 eski kasiyer/aşçı—yeni temizlikçiyi getirip her birine (artı sana) evin bir bölümünü versen, fazladan yardımla tüm işleri **paralel** yaparak çok daha çabuk bitirebilirdin.
Bu senaryoda, temizlikçilerin her biri (siz dahil) birer işlemci olacak ve üzerine düşeni yapacaktır.
Bu senaryoda, her bir temizlikçi (sen dâhil) birer işlemci olur ve kendi iş payını yapar.
Yürütme süresinin çoğu (beklemek yerine) iş yapıldığından ve bilgisayardaki iş bir <abbrtitle="Central Processing Unit">CPU</abbr>tarafından yapıldığından, bu sorunlara "CPU bound" diyorlar".
Ve yürütme süresinin çoğu gerçek işten (bekleme yerine) oluştuğu ve bilgisayardaki işi bir <abbrtitle="Central Processing Unit - Merkezi İşlem Birimi">CPU</abbr>yaptığı için, bu sorunlara "CPU bound" denir.
---
CPU'ya bağlı işlemlerin yaygın örnekleri, karmaşık matematik işlemleri gerektiren işlerdir.
CPU’ya bağlı işlemlerin yaygın örnekleri, karmaşık matematiksel işlem gerektiren iş yükleridir.
Örneğin:
* **Ses** veya **görüntü işleme**.
* **Bilgisayar görüsü**: bir görüntü milyonlarca pikselden oluşur, her pikselin 3 değeri / rengi vardır, bu pikseller üzerinde aynı anda bir şeyler hesaplamayı gerektiren işleme.
* **Makine Öğrenimi**: Çok sayıda "matris" ve "vektör" çarpımı gerektirir. Sayıları olan ve hepsini aynı anda çarpan büyük bir elektronik tablo düşünün.
* **Derin Öğrenme**: Bu, Makine Öğreniminin bir alt alanıdır, dolayısıyla aynısı geçerlidir. Sadece çarpılacak tek bir sayı tablosu değil, büyük bir sayı kümesi vardır ve çoğu durumda bu modelleri oluşturmak ve/veya kullanmak için özel işlemciler kullanırsınız.
* **Bilgisayar görüsü**: bir görüntü milyonlarca pikselden oluşur, her pikselin 3 değeri / rengi vardır; işleme genellikle bu pikseller üzerinde aynı anda bir şeyler hesaplamayı gerektirir.
* **Makine Öğrenimi**: genellikle çok sayıda "matris" ve "vektör" çarpımı gerekir. Sayılar içeren devasa bir elektronik tabloyu ve hepsini aynı anda çarpmayı düşünün.
* **Derin Öğrenme**: Makine Öğreniminin bir alt alanıdır, dolayısıyla aynısı geçerlidir. Sadece çarpılacak tek bir sayı tablosu değil, kocaman bir sayı kümesi vardır ve çoğu durumda bu modelleri kurmak ve/veya kullanmak için özel işlemciler kullanırsınız.
### Eşzamanlılık + Paralellik: Web + Makine Öğrenimi
**FastAPI** ile web geliştirme için çok yaygın olan eşzamanlılıktan yararlanabilirsiniz (NodeJS'in aynı çekiciliği).
**FastAPI** ile web geliştirmede çok yaygın olan eşzamanlılıktan (NodeJS’in başlıca cazibesiyle aynı) yararlanabilirsiniz.
Ancak, Makine Öğrenimi sistemlerindekile gibi **CPU'ya bağlı** iş yükleri için paralellik ve çoklu işlemenin (birden çok işlemin paralel olarak çalışması) avantajlarından da yararlanabilirsiniz.
Ama ayrıca **CPU’ya bağlı** iş yükleri (Makine Öğrenimi sistemlerindeki gibi) için paralellik ve çoklu işlemden (paralel çalışan birden çok işlem) de yararlanabilirsiniz.
Buna ek olarak Python'un **Veri Bilimi**, Makine Öğrenimi ve özellikle Derin Öğrenme için ana dil olduğu gerçeği, FastAPI'yi Veri Bilimi / Makine Öğrenimi web API'leri ve uygulamaları için çok iyi bir seçenek haline getirir.
Buna ek olarak Python’un **Veri Bilimi**, Makine Öğrenimi ve özellikle Derin Öğrenme için ana dil olması, FastAPI’yi Veri Bilimi / Makine Öğrenimi web API’leri ve uygulamaları için çok iyi bir seçenek yapar.
Production'da nasıl oldugunu görmek için şu bölüme bakın [Deployment](deployment/index.md){.internal-link target=_blank}.
Production’da bu paralelliği nasıl sağlayacağınızı görmek için [Deployment](deployment/index.md){.internal-link target=_blank} bölümüne bakın.
## `async` ve `await`
## `async` ve `await` { #async-and-await }
Python'un modern sürümleri, asenkron kodu tanımlamanın çok sezgisel bir yoluna sahiptir. Bu, normal "sequentıal" (sıralı) kod gibi görünmesini ve doğru anlarda sizin için "awaıt" ile bekleme yapmasını sağlar.
Python’un modern sürümleri, asenkron kodu tanımlamak için oldukça sezgisel bir yol sunar. Bu sayede kod normal "sıralı" kod gibi görünür ve doğru anlarda sizin yerinize "beklemeyi" yapar.
Sonuçları vermeden önce beklemeyi gerektirecek ve yeni Python özelliklerini destekleyen bir işlem olduğunda aşağıdaki gibi kodlayabilirsiniz:
Sonuçları vermeden önce bekleme gerektiren ve bu yeni Python özelliklerini destekleyen bir işlem olduğunda, şöyle kodlayabilirsiniz:
```Python
burgers = await get_burgers(2)
```
Buradaki `await` anahtari Python'a, sonuçları `burgers` degiskenine atamadan önce `get_burgers(2)` kodunun işini bitirmesini 🕙 beklemesi gerektiğini söyler. Bununla Python, bu ara zamanda başka bir şey 🔀 ⏯ yapabileceğini bilecektir (başka bir istek almak gibi).
Buradaki kilit nokta `await`. Python’a, sonuçları `burgers` değişkenine koymadan önce `get_burgers(2)` çalışmasının bitmesini 🕙 beklemesi ⏸ gerektiğini söyler. Böylece Python, bu arada başka bir şey 🔀 ⏯ yapabileceğini bilir (ör. başka bir request almak gibi).
`await`kodunun çalışması için, eşzamansızlığı destekleyen bir fonksiyonun içinde olması gerekir. Bunu da yapmak için fonksiyonu `async def` ile tanımlamamız yeterlidir:
`await`’in çalışabilmesi için, bu asenkronluğu destekleyen bir fonksiyonun içinde olması gerekir. Bunu yapmak için fonksiyonu `async def` ile tanımlayın:
```Python hl_lines="1"
async def get_burgers(number: int):
# burgerleri oluşturmak için asenkron birkaç iş
# Burgerleri yaratmak için bazı asenkron işler yap
return burgers
```
...`def` yerine:
```Python hl_lines="2"
# bu kod asenkron değil
# Bu asenkron değildir
def get_sequential_burgers(number: int):
# burgerleri oluşturmak için senkron bırkaç iş
# Burgerleri yaratmak için bazı sıralı işler yap
return burgers
```
`async def` ile Python, bu fonksıyonun içinde, `await` ifadelerinin farkında olması gerektiğini ve çalışma zamanı gelmeden önce bu işlevin yürütülmesini "duraklatabileceğini" ve başka bir şey yapabileceğini 🔀 bilir.
`async def` ile Python, bu fonksiyonun içinde `await` ifadelerinin olabileceğini bilir ve bu fonksiyonun yürütülmesini "duraklatıp" ⏸ başka bir şey yapabileceğini 🔀, sonra geri dönebileceğini anlar.
`async def` fonksiyonunu çağırmak istediğinizde, onu "awaıt" ıle kullanmanız gerekir. Yani, bu işe yaramaz:
`async def` fonksiyonunu çağırmak istediğinizde, onu "await" etmeniz gerekir. Yani şu çalışmaz:
```Python
# Bu işe yaramaz, çünkü get_burgers, şu şekilde tanımlandı: async def
# Bu çalışmaz, çünkü get_burgers şöyle tanımlandı: async def
burgers = get_burgers(2)
```
---
Bu nedenle, size onu `await` ile çağırabileceğinizi söyleyen bir kitaplık kullanıyorsanız, onu `async def` ile tanımlanan *path fonksiyonu* içerisinde kullanmanız gerekir, örneğin:
Dolayısıyla, `await` ile çağrılabileceğini söyleyen bir kütüphane kullanıyorsanız, onu kullanan *path operasyon fonksiyonunu*`async def` ile oluşturmanız gerekir, örneğin:
```Python hl_lines="2-3"
@app.get('/burgers')
@ -321,87 +349,96 @@ async def read_burgers():
return burgers
```
### Daha fazla teknik detay
### Daha teknik detaylar { #more-technical-details }
`await`’in yalnızca `async def` ile tanımlanan fonksiyonların içinde kullanılabildiğini fark etmiş olabilirsiniz.
Aynı zamanda, `async def` ile tanımlanan fonksiyonların da "await" edilmesi gerekir. Yani `async def` ile tanımlanan fonksiyonlar yalnızca `async def` ile tanımlanan fonksiyonların içinde çağrılabilir.
Peki, tavuk-yumurta meselesi: ilk `async` fonksiyon nasıl çağrılır?
**FastAPI** ile çalışıyorsanız bunu dert etmenize gerek yok; çünkü o "ilk" fonksiyon sizin *path operasyon fonksiyonunuz* olacaktır ve FastAPI doğru olanı yapmasını bilir.
`await` in yalnızca `async def` ile tanımlanan fonksıyonların içinde kullanılabileceğini fark etmişsinizdir.
Ama FastAPI olmadan da `async` / `await` kullanmak isterseniz, bunu da yapabilirsiniz.
Ama aynı zamanda, `async def` ile tanımlanan fonksiyonların "await" ile beklenmesi gerekir. Bu nedenle, "`async def` içeren fonksiyonlar yalnızca "`async def` ile tanımlanan fonksiyonların içinde çağrılabilir.
### Kendi async kodunuzu yazın { #write-your-own-async-code }
Starlette (ve **FastAPI**) <ahref="https://anyio.readthedocs.io/en/stable/"class="external-link"target="_blank">AnyIO</a> üzerine kuruludur; bu sayede Python standart kütüphanesindeki <ahref="https://docs.python.org/3/library/asyncio-task.html"class="external-link"target="_blank">asyncio</a> ve <ahref="https://trio.readthedocs.io/en/stable/"class="external-link"target="_blank">Trio</a> ile uyumludur.
Yani yumurta mı tavukdan, tavuk mu yumurtadan gibi ilk `async` fonksiyonu nasıl çağırılır?
Özellikle, kendi kodunuzda daha gelişmiş desenler gerektiren ileri seviye eşzamanlılık kullanım senaryoları için doğrudan <ahref="https://anyio.readthedocs.io/en/stable/"class="external-link"target="_blank">AnyIO</a> kullanabilirsiniz.
**FastAPI** ile çalışıyorsanız bunun için endişelenmenize gerek yok, çünkü bu "ilk" fonksiyon sizin *path fonksiyonunuz* olacak ve FastAPI doğru olanı nasıl yapacağını bilecek.
Hatta FastAPI kullanmıyor olsanız bile, yüksek uyumluluk ve avantajları (ör. *structured concurrency*) için <ahref="https://anyio.readthedocs.io/en/stable/"class="external-link"target="_blank">AnyIO</a> ile kendi async uygulamalarınızı yazabilirsiniz.
Ancak FastAPI olmadan `async` / `await` kullanmak istiyorsanız,<ahref="https://docs.python.org/3/library/asyncio-task.html#coroutine"class="external-link"target="_blank">resmi Python belgelerini kontrol edin</a>.
AnyIO’nun üzerine, tür açıklamalarını biraz iyileştirmek ve daha iyi **otomatik tamamlama**, **satır içi hatalar** vb. elde etmek için ince bir katman olarak başka bir kütüphane daha oluşturdum. Ayrıca **kendi async kodunuzu** anlamanıza ve yazmanıza yardımcı olacak dostça bir giriş ve eğitim içerir:<ahref="https://asyncer.tiangolo.com/"class="external-link"target="_blank">Asyncer</a>. Özellikle **async kodu normal** (bloklayan/senkron) **kodla birleştirmeniz** gerektiğinde faydalı olacaktır.
### Asenkron kodun diğer biçimleri
### Asenkron kodun diğer biçimleri { #other-forms-of-asynchronous-code }
Bu `async` ve `await` kullanimi oldukça yenidir.
`async` ve `await` kullanma tarzı, dilde nispeten yenidir.
Ancak asenkron kodla çalışmayı çok daha kolay hale getirir.
Ama asenkron kodla çalışmayı çok daha kolaylaştırır.
Aynı sözdizimi (hemen hemen aynı) son zamanlarda JavaScript'in modern sürümlerine de dahil edildi (Tarayıcı ve NodeJS'de).
Aynı (ya da neredeyse aynı) sözdizimi yakın zamanda modern JavaScript sürümlerine (Tarayıcı ve NodeJS) de eklendi.
Ancak bundan önce, asenkron kodu işlemek oldukça karmaşık ve zordu.
Bundan önce, asenkron kodu ele almak oldukça daha karmaşık ve zordu.
Python'un önceki sürümlerinde, threadlerı veya <ahref="https://www.gevent.org/"class="external-link"target="_blank">Gevent</a> kullanıyor olabilirdin. Ancak kodu anlamak, hata ayıklamak ve düşünmek çok daha karmaşık olurdu.
Python’un önceki sürümlerinde thread’ler veya <ahref="https://www.gevent.org/"class="external-link"target="_blank">Gevent</a> kullanabilirdiniz. Ama kodu anlamak, hata ayıklamak ve üzerine düşünmek çok daha zordu.
NodeJS / Browser JavaScript'in önceki sürümlerinde, "callback" kullanırdınız. Bu da "callbacks cehennemine" yol açar.
NodeJS / Tarayıcı JavaScript’in önceki sürümlerinde "callback" kullanırdınız. Bu da "callback cehennemi"ne yol açardı.
## Coroutine'ler
## Coroutine'ler { #coroutines }
**Coroutine**, bir `async def` fonksiyonu tarafından döndürülen değer için çok süslü bir terimdir. Python bunun bir fonksiyon gibi bir noktada başlayıp biteceğini bilir, ancak içinde bir `await` olduğunda dahili olarak da duraklatılabilir ⏸.
**Coroutine**, bir `async def` fonksiyonunun döndürdüğü şeye verilen süslü isimdir. Python bunun bir fonksiyona benzer bir şey olduğunu, bir noktada başlayıp biteceğini bilir; ama içinde bir `await` olduğunda dahili olarak duraklatılabileceğini ⏸ de bilir.
Ancak, `async` ve `await` ile asenkron kod kullanmanın tüm bu işlevselliği, çoğu zaman "Coroutine" kullanmak olarak adlandırılır. Go'nun ana özelliği olan "Goroutines" ile karşılaştırılabilir.
`async` ve `await` ile asenkron kod kullanmanın bu işlevselliği çoğu zaman "coroutine" kullanmak olarak özetlenir. Go’nun ana kilit özelliği olan "Goroutines" ile karşılaştırılabilir.
## Sonuç
## Sonuç { #conclusion }
Aynı ifadeyi yukarıdan görelim:
Yukarıdaki cümleyi tekrar görelim:
> Python'ın modern sürümleri, **"async" ve "await"** sözdizimi ile birlikte **"coroutines"** adlı bir özelliği kullanan**"asenkron kod"** desteğine sahiptir.
> Python’un modern sürümleri, **`async` ve `await`** sözdizimiyle, **"coroutines"** denilen bir yapıyı kullanarak**"asenkron kod"** desteğine sahiptir.
Şimdi daha mantıklı gelmeli. ✨
Artık daha anlamlı gelmeli. ✨
FastAPI'ye (Starlette aracılığıyla) güç veren ve bu kadar etkileyici bir performansa sahip olmasını sağlayan şey budur.
Bunların hepsi, FastAPI’ye (Starlette aracılığıyla) güç verir ve böylesine etkileyici bir performansa sahip olmasını sağlar.
## Çok Teknik Detaylar
## Çok Teknik Detaylar { #very-technical-details }
/// warning
/// warning | Uyarı
Muhtemelen burayı atlayabilirsiniz.
Büyük ihtimalle burayı atlayabilirsiniz.
Bunlar, **FastAPI**'nin altta nasıl çalıştığına dair çok teknik ayrıntılardır.
Bunlar, **FastAPI**’nin altında nasıl çalıştığına dair oldukça teknik ayrıntılardır.
Biraz teknik bilginiz varsa (co-routines, threads, blocking, vb)ve FastAPI'nin "async def" ile normal "def" arasındaki farkı nasıl işlediğini merak ediyorsanız, devam edin.
Coroutine’ler, thread’ler, blocking vb. hakkında teknik bilginiz varsa ve FastAPI’nin `async def` ile normal `def` arasındaki farkı nasıl ele aldığını merak ediyorsanız, devam edin.
"async def" yerine normal "def" ile bir *yol işlem işlevi* bildirdiğinizde, doğrudan çağrılmak yerine (sunucuyu bloke edeceğinden) daha sonra beklenen harici bir iş parçacığı havuzunda çalıştırılır.
Bir *path operasyon fonksiyonunu*`async def` yerine normal `def` ile tanımladığınızda, (sunucuyu bloklayacağından) doğrudan çağrılmak yerine, harici bir thread pool’da çalıştırılır ve ardından beklenir.
Yukarıda açıklanan şekilde çalışmayan başka bir asenkron framework'den geliyorsanız ve küçük bir performans kazancı (yaklaşık 100 nanosaniye) için "def" ile *path fonksiyonu* tanımlamaya alışkınsanız, **FastAPI**'de tam tersi olacağını unutmayın. Bu durumlarda, *path fonksiyonu*<abbrtitle="Input/Output: disk okuma veya yazma, ağ iletişimleri.">G/Ç</abbr> engelleyen durum oluşturmadıkça "async def" kullanmak daha iyidir.
Yukarıda açıklanan şekilde çalışmayan başka bir async framework’ten geliyorsanız ve ufak bir performans kazancı (yaklaşık 100 nanosaniye) için yalnızca hesaplama yapan basit *path operasyon fonksiyonlarını* düz `def` ile tanımlamaya alışkınsanız, **FastAPI**’de etkinin tam tersi olacağını unutmayın. Bu durumlarda, *path operasyon fonksiyonlarınız* bloklayan<abbrtitle="Input/Output - Giriş/Çıkış: disk okuma veya yazma, ağ iletişimi.">I/O</abbr> yapan kod kullanmadıkça `async def` kullanmak daha iyidir.
Yine de, her iki durumda da, **FastAPI**'nin önceki frameworkden [hala daha hızlı](index.md#performans){.internal-link target=_blank} (veya en azından karşılaştırılabilir) olma olasılığı vardır.
Yine de her iki durumda da, **FastAPI**’nin önceki framework’ünüzden [hala daha hızlı](index.md#performance){.internal-link target=_blank} (ya da en azından karşılaştırılabilir) olması muhtemeldir.
### Bagımlılıklar
### Bağımlılıklar { #dependencies }
Aynısı bağımlılıklar için de geçerlidir. Bir bağımlılık, "async def" yerine standart bir "def" işleviyse, harici iş parçacığı havuzunda çalıştırılır.
Aynısı [bağımlılıklar](tutorial/dependencies/index.md){.internal-link target=_blank} için de geçerlidir. Bir bağımlılık `async def` yerine standart bir `def` fonksiyonuysa, harici thread pool’da çalıştırılır.
### Alt-bağımlıklar
### Alt-bağımlılıklar { #sub-dependencies }
Birbirini gerektiren (fonksiyonlarin parametreleri olarak) birden fazla bağımlılık ve alt bağımlılıklarınız olabilir, bazıları 'async def' ve bazıları normal 'def' ile oluşturulabilir. Yine de normal 'def' ile oluşturulanlar, "await" kulanilmadan harici bir iş parçacığında (iş parçacığı havuzundan) çağrılır.
Birbirini gerektiren birden çok bağımlılık ve [alt-bağımlılık](tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} olabilir (fonksiyon tanımlarının parametreleri olarak). Bazıları `async def` ile, bazıları normal `def` ile oluşturulmuş olabilir. Yine de çalışır ve normal `def` ile oluşturulanlar "await" edilmek yerine harici bir thread’de (thread pool’dan) çağrılır.
### Diğer yardımcı fonksiyonlar
### Diğer yardımcı fonksiyonlar { #other-utility-functions }
Doğrudan çağırdığınız diğer herhangi bir yardımcı fonksiyonu, normal "def" veya "async def" ile tanimlayabilirsiniz. FastAPI onu çağırma şeklinizi etkilemez.
Doğrudan çağırdığınız diğer yardımcı fonksiyonları normal `def` veya `async def` ile tanımlayabilirsiniz ve FastAPI onları çağırma biçiminizi etkilemez.
Bu, FastAPI'nin sizin için çağırdığı fonksiyonlarin tam tersidir: *path fonksiyonu* ve bağımlılıklar.
Bu, FastAPI’nin sizin için çağırdığı fonksiyonların tersidir: *path operasyon fonksiyonları* ve bağımlılıklar.
Yardımcı program fonksiyonunuz 'def' ile normal bir işlevse, bir iş parçacığı havuzunda değil doğrudan (kodunuzda yazdığınız gibi) çağrılır, işlev 'async def' ile oluşturulmuşsa çağırıldığı yerde 'await' ile beklemelisiniz.
Yardımcı fonksiyonunuz `def` ile tanımlı normal bir fonksiyonsa, bir thread pool’da değil doğrudan (kodunuzda yazdığınız gibi) çağrılır; fonksiyon `async def` ile tanımlıysa kodunuzda çağırırken onu `await` etmelisiniz.
---
Yeniden, bunlar, onları aramaya geldiğinizde muhtemelen işinize yarayacak çok teknik ayrıntılardır.
Yine, bunlar muhtemelen özellikle aradığınızda işinize yarayacak çok teknik ayrıntılardır.
Aksi takdirde, yukarıdaki bölümdeki yönergeleri iyi bilmelisiniz: <ahref="#in-a-hurry">Aceleniz mi var?</a>.
Aksi hâlde, yukarıdaki bölümdeki yönergeler yeterlidir: <ahref="#in-a-hurry">Aceleniz mi var?</a>.
@ -13,7 +13,7 @@ Bir **FastAPI** uygulamasını (hatta genel olarak herhangi bir web API'yi) depl
Bunların **deployment**'ları nasıl etkilediğine bakalım.
Nihai hedef, **API client**'larınıza **güvenli** bir şekilde hizmet verebilmek, **kesintileri** önlemek ve **hesaplama kaynaklarını** (ör. uzak server'lar/sanal makineler) olabildiğince verimli kullanmaktır.
Nihai hedef, **API client**'larınıza **güvenli** bir şekilde hizmet verebilmek, **kesintileri** önlemek ve **hesaplama kaynaklarını** (ör. uzak server'lar/sanal makineler) olabildiğince verimli kullanmaktır. 🚀
Burada bu **kavramlar** hakkında biraz daha bilgi vereceğim. Böylece, çok farklı ortamlarda—hatta bugün var olmayan **gelecekteki** ortamlarda bile—API'nizi nasıl deploy edeceğinize karar verirken ihtiyaç duyacağınız **sezgiyi** kazanmış olursunuz.
@ -21,7 +21,7 @@ Bu kavramları dikkate alarak, **kendi API**'leriniz için en iyi deployment yak
Sonraki bölümlerde, FastAPI uygulamalarını deploy etmek için daha **somut tarifler** (recipes) paylaşacağım.
Ama şimdilik, bu önemli **kavramsal fikirleri** inceleyelim. Bu kavramlar diğer tüm web API türleri için de geçerlidir.
Ama şimdilik, bu önemli **kavramsal fikirleri** inceleyelim. Bu kavramlar diğer tüm web API türleri için de geçerlidir. 💡
## Güvenlik - HTTPS { #security-https }
@ -36,16 +36,16 @@ Ve **HTTPS sertifikalarını yenilemekten** sorumlu bir şey olmalıdır; bu ayn
TLS Termination Proxy olarak kullanabileceğiniz bazı araçlar:
* Traefik
* Sertifika yenilemelerini otomatik yönetir
* Sertifika yenilemelerini otomatik yönetir ✨
* Caddy
* Sertifika yenilemelerini otomatik yönetir
* Sertifika yenilemelerini otomatik yönetir ✨
* Nginx
* Sertifika yenilemeleri için Certbot gibi harici bir bileşenle
* HAProxy
* Sertifika yenilemeleri için Certbot gibi harici bir bileşenle
* Nginx gibi bir Ingress Controller ile Kubernetes
* Sertifika yenilemeleri için cert-manager gibi harici bir bileşenle
* Bir cloud provider tarafından servislerinin parçası olarak içeride yönetilmesi (aşağıyı okuyun)
* Bir cloud provider tarafından servislerinin parçası olarak içeride yönetilmesi (aşağıyı okuyun 👇)
Bir diğer seçenek de, HTTPS kurulumunu da dahil olmak üzere işin daha büyük kısmını yapan bir **cloud service** kullanmaktır. Bunun bazı kısıtları olabilir veya daha pahalı olabilir vb. Ancak bu durumda TLS Termination Proxy'yi kendiniz kurmak zorunda kalmazsınız.
@ -100,7 +100,7 @@ Bu yöntem çalışır ve **geliştirme sırasında** faydalıdır.
Ancak server'a olan bağlantınız koparsa, **çalışan process** muhtemelen ölür.
Ve server yeniden başlatılırsa (örneğin update'lerden sonra ya da cloud provider'ın migration'larından sonra) bunu muhtemelen **fark etmezsiniz**. Dolayısıyla process'i manuel yeniden başlatmanız gerektiğini de bilmezsiniz. Sonuçta API'niz ölü kalır.
Ve server yeniden başlatılırsa (örneğin update'lerden sonra ya da cloud provider'ın migration'larından sonra) bunu muhtemelen **fark etmezsiniz**. Dolayısıyla process'i manuel yeniden başlatmanız gerektiğini de bilmezsiniz. Sonuçta API'niz ölü kalır. 😱
### Startup'ta Otomatik Çalıştırma { #run-automatically-on-startup }
@ -131,19 +131,19 @@ Uygulamanızın startup'ta çalıştığından emin olmaya benzer şekilde, hata
### Hata Yaparız { #we-make-mistakes }
Biz insanlar sürekli **hata** yaparız. Yazılımın neredeyse *her zaman* farklı yerlerinde gizli **bug**'lar vardır.
Biz insanlar sürekli **hata** yaparız. Yazılımın neredeyse *her zaman* farklı yerlerinde gizli **bug**'lar vardır. 🐛
Ve biz geliştiriciler bu bug'ları buldukça ve yeni özellikler ekledikçe code'u iyileştiririz (muhtemelen yeni bug'lar da ekleyerek).
Ve biz geliştiriciler bu bug'ları buldukça ve yeni özellikler ekledikçe code'u iyileştiririz (muhtemelen yeni bug'lar da ekleyerek 😅).
### Küçük Hatalar Otomatik Yönetilir { #small-errors-automatically-handled }
FastAPI ile web API geliştirirken, code'umuzda bir hata olursa FastAPI genellikle bunu hatayı tetikleyen tek request ile sınırlar.
FastAPI ile web API geliştirirken, code'umuzda bir hata olursa FastAPI genellikle bunu hatayı tetikleyen tek request ile sınırlar. 🛡
Client o request için **500 Internal Server Error** alır; ancak uygulama tamamen çöküp durmak yerine sonraki request'ler için çalışmaya devam eder.
### Daha Büyük Hatalar - Çökmeler { #bigger-errors-crashes }
Yine de bazı durumlarda, yazdığımız bir code **tüm uygulamayı çökertip** Uvicorn ve Python'ın crash olmasına neden olabilir.
Yine de bazı durumlarda, yazdığımız bir code **tüm uygulamayı çökertip** Uvicorn ve Python'ın crash olmasına neden olabilir. 💥
Böyle bir durumda, tek bir noktadaki hata yüzünden uygulamanın ölü kalmasını istemezsiniz; bozuk olmayan *path operations* en azından çalışmaya devam etsin istersiniz.
@ -206,7 +206,7 @@ Ve birden fazla process normalde **belleği paylaşmaz**. Yani her çalışan pr
Örneğin code'unuz **1 GB** boyutunda bir Machine Learning modelini yüklüyorsa, API'niz tek process ile çalışırken en az 1 GB RAM tüketir. **4 process** (4 worker) başlatırsanız her biri 1 GB RAM tüketir. Yani toplamda API'niz **4 GB RAM** tüketir.
Uzak server'ınız veya sanal makineniz yalnızca 3 GB RAM'e sahipse, 4 GB'tan fazla RAM yüklemeye çalışmak sorun çıkarır.
Uzak server'ınız veya sanal makineniz yalnızca 3 GB RAM'e sahipse, 4 GB'tan fazla RAM yüklemeye çalışmak sorun çıkarır. 🚨
### Birden Fazla Process - Bir Örnek { #multiple-processes-an-example }
@ -265,7 +265,7 @@ Elbette bazı durumlarda ön adımları birden fazla kez çalıştırmak sorun d
Ayrıca, kurulumunuza bağlı olarak bazı durumlarda uygulamanızı başlatmadan önce **hiç ön adıma ihtiyaç duymayabilirsiniz**.
Bu durumda bunların hiçbirini düşünmeniz gerekmez.
Bu durumda bunların hiçbirini düşünmeniz gerekmez. 🤷
///
@ -291,7 +291,7 @@ Server(lar)ınız bir **kaynaktır**. Programlarınızla CPU'lardaki hesaplama z
Sistem kaynaklarının ne kadarını tüketmek/kullanmak istersiniz? "Az" demek kolaydır; ancak pratikte hedef genellikle **çökmeden mümkün olduğunca fazla** kullanmaktır.
3 server için para ödüyor ama onların RAM ve CPU'sunun yalnızca küçük bir kısmını kullanıyorsanız, muhtemelen **para israf ediyorsunuz** ve muhtemelen **elektrik tüketimini** de gereksiz yere artırıyorsunuz vb.
3 server için para ödüyor ama onların RAM ve CPU'sunun yalnızca küçük bir kısmını kullanıyorsanız, muhtemelen **para israf ediyorsunuz**💸 ve muhtemelen **elektrik tüketimini** de gereksiz yere artırıyorsunuz 🌎 vb.
Bu durumda 2 server ile devam edip onların kaynaklarını (CPU, bellek, disk, ağ bant genişliği vb.) daha yüksek oranlarda kullanmak daha iyi olabilir.
@ -316,6 +316,6 @@ Uygulamanızı nasıl deploy edeceğinize karar verirken aklınızda tutmanız g
* Bellek
* Başlatmadan önceki adımlar
Bu fikirleri ve nasıl uygulayacağınızı anlamak, deployment'larınızı yapılandırırken ve ince ayar yaparken ihtiyaç duyacağınız sezgiyi kazanmanızı sağlamalıdır.
Bu fikirleri ve nasıl uygulayacağınızı anlamak, deployment'larınızı yapılandırırken ve ince ayar yaparken ihtiyaç duyacağınız sezgiyi kazanmanızı sağlamalıdır. 🤓
Sonraki bölümlerde, izleyebileceğiniz stratejilere dair daha somut örnekler paylaşacağım.
Sonraki bölümlerde, izleyebileceğiniz stratejilere dair daha somut örnekler paylaşacağım. 🚀
## Replication - Process Sayısı { #replication-number-of-processes }
Kubernetes, Docker Swarm Mode, Nomad veya benzeri, birden fazla makinede dağıtık container'ları yöneten karmaşık bir sistemle kurulmuş bir <abbrtitle="Bir şekilde birbirine bağlanacak ve birlikte çalışacak şekilde yapılandırılmış makineler grubu.">cluster</abbr>'ınız varsa, replication'ı her container içinde bir **process manager** (ör. worker'lı Uvicorn) kullanarak yönetmek yerine, muhtemelen **cluster seviyesinde** ele almak istersiniz.
Eğer bir <dfntitle="Bir şekilde birbirine bağlanacak ve birlikte çalışacak şekilde yapılandırılmış makineler grubu.">küme</dfn> (cluster) olarak yapılandırılmış makineler grubunuz varsa ve bunları **Kubernetes**, Docker Swarm Mode, Nomad veya benzeri, birden çok makinede dağıtık container'ları yöneten karmaşık bir sistemle yönetiyorsanız, replication'ı her container içinde bir **process manager** (ör. worker'lı Uvicorn) kullanarak yönetmek yerine, muhtemelen **küme seviyesinde (cluster level)** ele almak istersiniz.
Kubernetes gibi dağıtık container yönetim sistemleri, gelen request'ler için **load balancing** desteği sunarken aynı zamanda **container replication**'ını yönetmek için entegre mekanizmalara sahiptir. Hepsi **cluster seviyesinde**.
@ -499,7 +499,7 @@ Elbette bazı **özel durumlarda** bir container içinde birden fazla **Uvicorn
Bu durumlarda çalıştırmak istediğiniz worker sayısını `--workers` komut satırı seçeneğiyle ayarlayabilirsiniz:
@ -65,7 +65,7 @@ Burada, bir HTTPS API’nin adım adım nasıl görünebileceğine dair, özelli
Muhtemelen her şey, bir **domain adı****temin etmenizle** başlar. Sonra bunu bir DNS server’ında (muhtemelen aynı cloud provider’ınızda) yapılandırırsınız.
Muhtemelen bir cloud server (virtual machine) ya da benzeri bir şey alırsınız ve bunun <abbrtitle="That doesn't change - Bu değişmez">fixed</abbr> bir **public IP adresi** olur.
Muhtemelen bir cloud server (virtual machine) ya da benzeri bir şey alırsınız ve bunun <dfntitle="Zamanla değişmeyen. Dinamik olmayan.">sabit</dfn> bir **public IP adresi** olur.
DNS server(lar)ında, bir kaydı ("`A record`") **domain**’inizi server’ınızın **public IP adresine** yönlendirecek şekilde yapılandırırsınız.
**FastAPI** uygulamasını deploy etmek nispeten kolaydır.
## Deployment Ne Anlama Gelir? { #what-does-deployment-mean }
## Dağıtım Ne Anlama Gelir? { #what-does-deployment-mean }
Bir uygulamayı **deploy** etmek, onu **kullanıcılara erişilebilir hale getirmek** için gerekli adımları gerçekleştirmek anlamına gelir.
@ -10,7 +10,7 @@ Bir **web API** için bu süreç normalde uygulamayı **uzak bir makineye** yerl
Bu, kodu sürekli olarak değiştirdiğiniz, bozup düzelttiğiniz, geliştirme sunucusunu durdurup yeniden başlattığınız vb. **geliştirme** aşamalarının tam tersidir.
@ -46,7 +46,7 @@ Bu, çoğu durumda işinizi görür. 😎
Şimdi biraz daha detaya inelim.
FastAPI, Python web framework'leri ve sunucularını inşa etmek için kullanılan <abbrtitle="Asynchronous Server Gateway Interface">ASGI</abbr> adlı bir standardı kullanır. FastAPI bir ASGI web framework'üdür.
FastAPI, Python web framework'leri ve sunucularını inşa etmek için kullanılan <abbrtitle="Asynchronous Server Gateway Interface - Asenkron Sunucu Ağ Geçidi Arayüzü">ASGI</abbr> adlı bir standardı kullanır. FastAPI bir ASGI web framework'üdür.
Uzak bir sunucu makinesinde **FastAPI** uygulamasını (veya herhangi bir ASGI uygulamasını) çalıştırmak için gereken ana şey, **Uvicorn** gibi bir ASGI server programıdır. `fastapi` komutuyla varsayılan olarak gelen de budur.
@ -74,7 +74,7 @@ FastAPI'yi kurduğunuzda, production sunucusu olarak Uvicorn da beraberinde geli
Ancak bir ASGI server'ı manuel olarak da kurabilirsiniz.
Bir [virtual environment](../virtual-environments.md){.internal-link target=_blank} oluşturduğunuzdan, etkinleştirdiğinizden emin olun; ardından server uygulamasını kurabilirsiniz.
Bir [sanal ortam](../virtual-environments.md){.internal-link target=_blank} oluşturduğunuzdan, etkinleştirdiğinizden emin olun; ardından server uygulamasını kurabilirsiniz.
Bu konuyla ilgili daha fazlasını <ahref="https://12factor.net/config"class="external-link"target="_blank">The Twelve-Factor App: Config</a> bölümünde okuyabilirsiniz.
Bu konuyla ilgili daha fazlasını <ahref="https://12factor.net/config"class="external-link"target="_blank">Twelve-Factor Uygulaması: Config</a> bölümünde okuyabilirsiniz.
///
@ -291,7 +291,7 @@ Bu bilgiler, [Virtual Environments](virtual-environments.md){.internal-link targ
Buraya kadar **ortam değişkenleri**nin ne olduğuna ve Python’da nasıl kullanılacağına dair temel bir fikir edinmiş olmalısınız.
Ayrıca <ahref="https://en.wikipedia.org/wiki/Environment_variable"class="external-link"target="_blank">Wikipedia for Environment Variable</a> sayfasından daha fazlasını da okuyabilirsiniz.
Ayrıca <ahref="https://en.wikipedia.org/wiki/Environment_variable"class="external-link"target="_blank">Ortam Değişkeni için Wikipedia</a> sayfasından daha fazlasını da okuyabilirsiniz.
Çoğu zaman ortam değişkenlerinin hemen nasıl işe yarayacağı ilk bakışta çok net olmayabilir. Ancak geliştirme yaparken birçok farklı senaryoda tekrar tekrar karşınıza çıkarlar; bu yüzden bunları bilmek faydalıdır.
### Açık Standartlara Dayalı { #based-on-open-standards }
* API oluşturma işlemlerinde<ahref="https://github.com/OAI/OpenAPI-Specification"class="external-link"target="_blank"><strong>OpenAPI</strong></a> buna <abbrtitle="also known as: endpoints, routes">path</abbr><abbrtitle=" HTTP metodları olarak bilinen, POST, GET, PUT, DELETE">operasyonları</abbr>parametreleri, body talebi, güvenlik gibi şeyler dahil olmak üzere deklare bunların deklare edilmesi.
* Otomatik olarak data modelinin <ahref="http://json-schema.org/"class="external-link"target="_blank"><strong>JSON Schema</strong></a> ile beraber dokümante edilmesi (OpenAPI'n kendisi zaten JSON Schema'ya dayanıyor).
* Titiz bir çalışmanın sonucunda yukarıdaki standartlara uygun bir framework oluşturduk. Standartları pastanın üzerine sonradan eklenmiş bir çilek olarak görmedik.
* Ayrıca bu bir çok dilde kullanılabilecek **client code generator** kullanımına da izin veriyor.
* API oluşturmada<ahref="https://github.com/OAI/OpenAPI-Specification"class="external-link"target="_blank"><strong>OpenAPI</strong></a>, buna <dfntitle="şöyle de bilinir: endpoints, routes">path</dfn><dfntitle="HTTP metodları olarak da bilinir; POST, GET, PUT, DELETE gibi">operasyonları</dfn>, parametreler, request body'leri, güvenlik vb. deklarasyonları dahildir.
* <ahref="https://json-schema.org/"class="external-link"target="_blank"><strong>JSON Schema</strong></a> ile otomatik veri modeli dokümantasyonu (OpenAPI zaten JSON Schema'ya dayanır).
* Bu standartlar etrafında, titiz bir çalışmanın ardından tasarlandı; sonradan eklenmiş bir katman değil.
* Bu sayede birçok dilde otomatik **client code generation** da kullanılabilir.
### Otomatik dokümantasyon
### Otomatik Dokümantasyon { #automatic-docs }
Etkileşimli API dokümantasyonu ve keşif için web arayüzleri. Framework OpenAPI’ye dayandığından, birden fazla seçenek vardır; varsayılan olarak 2’si dahildir.
OpenAPI standartlarına dayalı olan bir framework olarak, geliştiricilerin birden çok seçeneği var, varsayılan olarak gelen 2 farklı interaktif API dokümantasyonu ve web kullanıcı arayüzü var.
* <ahref="https://github.com/swagger-api/swagger-ui"class="external-link"target="_blank"><strong>Swagger UI</strong></a> interaktif olarak API'ınızı tarayıcı üzerinden çağırıp test edebilmenize olanak sağlıyor.
* <ahref="https://github.com/swagger-api/swagger-ui"class="external-link"target="_blank"><strong>Swagger UI</strong></a> ile etkileşimli keşif; API’nizi tarayıcıdan doğrudan çağırıp test edin.
Tamamiyle standartlar **Python 3.8**'nın type hintlerine dayanıyor (Pydantic'in sayesinde). Yeni bir syntax öğrenmene gerek yok. Sadece modern Python.
Her şey standart **Python type** deklarasyonlarına dayanır (Pydantic sayesinde). Öğrenilecek yeni bir söz dizimi yok. Sadece standart, modern Python.
Python type’larını nasıl kullanacağınıza dair 2 dakikalık bir hatırlatmaya ihtiyacınız varsa (FastAPI kullanmasanız bile) kısa eğitime göz atın: [Python Types](python-types.md){.internal-link target=_blank}.
Eğer Python type hintlerini bilmiyorsan veya bir hatırlatmaya ihtiyacın var ise(FastAPI kullanmasan bile) şu iki dakikalık küçük bilgilendirici içeriğe bir göz at: [Python Types](python-types.md){.internal-link target=_blank}.
Standart Python'u typelarını belirterek yazıyorsun:
Türleriyle standart Python yazarsınız:
```Python
from typing import List, Dict
from datetime import date
from pydantic import BaseModel
# Değişkeni str olarak belirt
# ve o fonksiyon için harika bir editör desteği al
# Bir değişkeni str olarak belirt
# ve fonksiyon içinde editör desteği al
def main(user_id: str):
return user_id
# Pydantic modeli
# Bir Pydantic modeli
class User(BaseModel):
id: int
name: str
joined: date
```
Sonrasında bu şekilde kullanabilirsin
Sonra şöyle kullanabilirsiniz:
```Python
my_user: User = User(id=3, name="John Doe", joined="2018-07-19")
@ -67,25 +63,26 @@ second_user_data = {
my_second_user: User = User(**second_user_data)
```
/// info
`**second_user_data` şu anlama geliyor:
`**second_user_data` şu anlama gelir:
Key-Value çiftini direkt olarak `second_user_data` dictionarysine kaydet , yaptığın şey buna eşit olacak: `User(id=4, name="Mary", joined="2018-11-30")`
`second_user_data` dict’indeki anahtar ve değerleri doğrudan anahtar-değer argümanları olarak geç; şu ifadeye eşdeğerdir: `User(id=4, name="Mary", joined="2018-11-30")`
///
### Editor desteği
### Editör Desteği { #editor-support }
Bütün framework kullanılması kolay ve sezgileri güçlü olması için tasarlandı, verilen bütün kararlar geliştiricilere en iyi geliştirme deneyimini yaşatmak üzere, bir çok editör üzerinde test edildi.
Tüm framework, kullanımı kolay ve sezgisel olacak şekilde tasarlandı; en iyi geliştirme deneyimini sağlamak için geliştirmeye başlamadan önce bile alınan kararlar birden çok editörde test edildi.
Son yapılan Python geliştiricileri anketinde, açık ara<ahref="https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features"class="external-link"target="_blank">en çok kullanılan özellik "oto-tamamlama" idi.</a>.
Python geliştirici anketlerinde açıkça görülüyor ki<ahref="https://www.jetbrains.com/research/python-developers-survey-2017/#tools-and-features"class="external-link"target="_blank">en çok kullanılan özelliklerden biri "otomatik tamamlama"</a>.
Bütün **FastAPI** frameworkü oto-tamamlama açısından geliştiriciyi tatmin etmek üzerine tasarlandı. Otomatik tamamlama her yerde çalışıyor.
Tüm **FastAPI** bunun tatmin edilmesi üzerine kuruldu. Otomatik tamamlama her yerde çalışır.
Dokümantasyona tekrardan çok nadir olarak geleceksin.
Dokümana geri dönmeniz nadiren gerekecek.
Editörün sana nasıl yardım ettiğine bir bak:
Editörünüz şöyle yardımcı olabilir:
* <ahref="https://code.visualstudio.com/"class="external-link"target="_blank">Visual Studio Code</a> ile:
@ -95,115 +92,111 @@ Editörün sana nasıl yardım ettiğine bir bak:
Daha önce imkânsız olduğunu düşünebileceğiniz yerlerde bile tamamlama alırsınız. Örneğin, bir request’ten gelen (iç içe de olabilir) JSON body içindeki `price` anahtarı için.
Daha önceden düşünüp en imkansız diyebileceğin durumlarda bile otomatik tamamlama alacaksın, örnek olarak `price` JSON body içerisinde (nested bir JSON body de olabilirdi.) direkt olarak istekten geliyor, bu durumda bile oto-tammalama sağlıyor.
Artık anahtar adlarını yanlış yazmak, dokümana gidip gelmek ya da sonunda `username` mi `user_name` mi kullandığınızı bulmak için sayfayı yukarı aşağı kaydırmak yok.
Artık key isimlerini yanlış yazma, dokümantasyona dönüp deliler gibi yukarı aşağı sayfada gezmek ve en sonunda `username` mi yoksa `user_name` mi kullandım gibi sorular yok.
### Kısa { #short }
### Kısa
Her şey için mantıklı **varsayılanlar** ve her yerde isteğe bağlı yapılandırmalar vardır. Tüm parametreler, ihtiyacınızı karşılayacak şekilde ince ayar yapılarak tanımlamak istediğiniz API’yi oluşturabilir.
Her şey için mantıklı bir **varsayılanı** var. Parametrelerini opsiyonel olarak tanımlayıp API'nı istediğin gibi modifiye edebilirsin.
Ancak varsayılan hâliyle hepsi **“hemen çalışır”**.
Hepsi varsayılan olarak **çalışıyor**.
### Doğrulama { #validation }
* Çoğu (veya hepsi?) Python **veri tipi** için doğrulama, şunlar dâhil:
* Minimum ve maksimum uzunlukları tanımlanan String (`str`) alanları.
* Min ve max değerleri olan sayılar (`int`, `float`) vb.
### Doğrulama
* Neredeyse bütün (ya da hepsi?) Python **data typeları** için doğrulama, kapsadıkları:
* JSON objeleri (`dict`).
* JSON array (`list`) item type'ı belirtirken.
* String (`str`) parametresi, minimum ve maksimum uzunluk gibi sınırlandırmalar yaparken.
* Numaralar (`int`, `float`) maksimum ve minimum gibi sınırlandırmalar yaparken.
* Bunlar gibi en egzotik typelarla bile doğrulama yapabiliyorsunuz.:
* Daha “egzotik” tipler için doğrulama:
* URL.
* Email.
* UUID.
* ...ve diğerleri.
Bütün doğrulama olayları çok güçlü bir kütüphane sayesinde yapılıyor, **Pydantic**.
Tüm doğrulama köklü ve sağlam **Pydantic** tarafından yapılır.
### Güvenlik ve kimlik doğrulama
### Güvenlik ve Kimlik Doğrulama { #security-and-authentication }
Güvenlik ve doğrulama database ve data modellerinden taviz vermeden entegre edilebilir durumda.
Güvenlik ve kimlik doğrulama entegredir. Veritabanları veya veri modelleriyle ilgili hiçbir taviz yoktur.
Bütün güvenlik şemaları OpenAPI'da tanımlanmış durumda, kapsadıkları:
OpenAPI’da tanımlanan tüm güvenlik şemaları, şunlar dâhil:
* HTTP Basic.
* **OAuth2** (ve **JWT tokenleriyle** beraber). Bu öğretici içeriğe göz atabilirsin [OAuth2 with JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}.
* **OAuth2** (ayrıca **JWT token**’larla). Şu eğitime göz atın: [OAuth2 with JWT](tutorial/security/oauth2-jwt.md){.internal-link target=_blank}.
* API anahtarları:
* Headerlar.
* Query parametreleri.
* Cookies, vs.
Bütün güvenlik özellikleri Starlette'den geliyor (**session cookies'de** dahil olmak üzere).
* Header’larda.
* Query parametrelerinde.
* Cookie’lerde vb.
Bütün hepsi tekrardan kullanılabilir aletler ve bileşenler olarak, kolayca sistemlerinize, data depolarınıza, ilişkisel ve NoSQL databaselerinize entegre edebileceğiniz şekilde yapıldı.
Buna ek olarak Starlette’in tüm güvenlik özellikleri (**session cookies** dâhil).
### Dependency injection
Tümü, sistemleriniz, veri depolarınız, ilişkisel ve NoSQL veritabanlarınız vb. ile kolayca entegre edilebilen, yeniden kullanılabilir araçlar ve bileşenler olarak inşa edilmiştir.
FastAPI'ın inanılmaz derecede kullanımı kolay, fakat inanılmaz derecede güçlü <abbrtitle='"components", "resources", "services", "providers" olarak da bilinen'><strong>Dependency Injection </strong></abbr> sistemi var.
* Dependencylerin bile dependencies'i olabiliyor, FastAPI bunun için **graph of "dependency"** yaratıyor.
* Hepsi **otomatik olarak** FastAPI tarafından hallediliyor.
* Bütün zorunlulukların gelen datalara bağlı olarak farklı gereksinimleri olabiliyor, ilave path operasyonlarının kısıtlamaları ve otomatik dokümantasyonu da ayrıca yapılıyor .
* Path operasyonu parametreleri içerisinde belirtilen gereksinimler için bile **Otomatik doğrulama** yapılabiliyor.
* Kompleks kimlik doğrulama sistemleri için destek, **database bağlantıları**, vs.
* **Taviz yok** hiçbir şeyden taviz vermeden, database frontend vs. Bütün hepsinin kolayca entegre edilebiliyor.
FastAPI, son derece kolay kullanımlı ama son derece güçlü bir <dfntitle='şöyle de bilinir: "components", "resources", "services", "providers"'><strong>Dependency Injection</strong></dfn> sistemine sahiptir.
### Sınırsız "plug-inler"
* Bağımlılıkların da kendi bağımlılıkları olabilir; böylece bir hiyerarşi veya **bağımlılıklar "grafı"** oluşur.
* Tüm süreç framework tarafından **otomatik olarak yönetilir**.
* Tüm bağımlılıklar, request’lerden veri talep edebilir ve *path operation* kısıtlarını ve otomatik dokümantasyonu **zenginleştirebilir**.
* Bağımlılıklarda tanımlanan *path operation* parametreleri için bile **otomatik doğrulama**.
* Karmaşık kullanıcı kimlik doğrulama sistemleri, **veritabanı bağlantıları** vb. için destek.
* Veritabanları, frontend’ler vb. ile **taviz yok**; ancak hepsiyle kolay entegrasyon.
Başka bir deyişle, plug-inlere ihtiyacımız yok, import edip direkt olarak kullanmaya başlayabiliriz.
### Sınırsız "Plug-in" { #unlimited-plug-ins }
Bütün entegrasyonlar kullanımı kolay olmak üzere (zorunluluklar ile beraber) tasarlandı, sen bir "plug-in" yaratıp 2 satır kod ile, *path operasyonlarında* kullandığımız syntax ve aynı yapı ile koduna entregre edebilirsin.
Başka bir deyişle, onlara gerek yok; ihtiyaç duyduğunuz kodu import edin ve kullanın.
Her entegrasyon (bağımlılıklar ile) o kadar basit olacak şekilde tasarlanmıştır ki, uygulamanız için, *path operations* ile kullandığınız aynı yapı ve söz dizimiyle sadece 2 satırda bir “plug-in” yazabilirsiniz.
### Test edildi
### Test Edildi { #tested }
* 100% <abbrtitle="Kodun ne kadarının test edildiği">test coverage</abbr>.
* 100% <abbrtitle="Python type annotations, with this your editor and external tools can give you better support">typeları belirtilmiş</abbr> codebase.
* FastAPI ile yapılan bir çok proje insanlar tarafından kullanılıyor.
* %100 <dfntitle="Otomatik olarak test edilen kod miktarı">test kapsayıcılığı</dfn>.
* %100 <dfntitle="Python type annotations; bununla editörünüz ve harici araçlar size daha iyi destek verebilir">type annotated</dfn> kod tabanı.
* Üretimde kullanılan uygulamalarda kullanılıyor.
## Starlette özellikleri
## Starlette Özellikleri { #starlette-features }
**FastAPI**, <ahref="https://www.starlette.dev/"class="external-link"target="_blank"><strong>Starlette</strong></a> ile tamamiyle uyumlu ve üzerine kurulu. Yani FastAPI üzerine ekleme yapacağınız herhangi bir Starlette kodu da çalışacaktır.
**FastAPI**, <ahref="https://www.starlette.dev/"class="external-link"target="_blank"><strong>Starlette</strong></a> ile tamamen uyumludur (ve onun üzerine kuruludur). Dolayısıyla elinizdeki ek Starlette kodları da çalışır.
`FastAPI` aslında `Starlette`'nin bir sub-class'ı. Eğer Starlette'nin nasıl kullanılacağını biliyor isen, çoğu işlevini aynı şekilde yapıyor.
`FastAPI` aslında `Starlette`’in bir alt sınıfıdır. Starlette’i zaten biliyor veya kullanıyorsanız, işlevlerin çoğu aynı şekilde çalışır.
**FastAPI** ile beraber **Starlette**'nin bütün özelliklerine de sahip olacaksınız (FastAPI aslında Starlette'nin steroid basmış hali):
**FastAPI** ile **Starlette**’in tüm özelliklerini elde edersiniz (FastAPI, steroid basılmış Starlette gibidir):
* Gerçekten etkileyici bir performansa sahip.Python'un ise en hızlı frameworklerinden bir tanesi,<ahref="https://github.com/encode/starlette#performance"class="external-link"target="_blank">**NodeJS** ve **Go** ile ise eşdeğer performansa sahip.</a>.
* Cidden etkileyici performans.<ahref="https://github.com/encode/starlette#performance"class="external-link"target="_blank">Mevcut en hızlı Python frameworklerinden biridir; **NodeJS** ve **Go** ile aynı seviyededir</a>.
* **WebSocket** desteği.
* **GraphQL** desteği.
* Kullanım halinde arka plan işlevleri.
* Başlatma ve kapatma eventleri(startup and shutdown).
**FastAPI** ile<ahref="https://docs.pydantic.dev/"class="external-link"target="_blank"><strong>Pydantic</strong></a>tamamiyle uyumlu ve üzerine kurulu. Yani FastAPI üzerine ekleme yapacağınız herhangi bir Pydantic kodu da çalışacaktır.
**FastAPI**,<ahref="https://docs.pydantic.dev/"class="external-link"target="_blank"><strong>Pydantic</strong></a>ile tamamen uyumludur (ve onun üzerine kuruludur). Dolayısıyla elinizdeki ek Pydantic kodları da çalışır.
Bunlara Pydantic üzerine kurulu<abbrtitle="Object-Relational Mapper">ORM</abbr> databaseler ve , <abbrtitle="Object-Document Mapper">ODM</abbr> kütüphaneler de dahil olmak üzere.
Pydantic’e dayanan harici kütüphaneler de dâhildir; veritabanları için<abbrtitle="Object-Relational Mapper - Nesne-İlişkisel Eşleyici">ORM</abbr>’ler, <abbrtitle="Object-Document Mapper - Nesne-Belge Eşleyici">ODM</abbr>’ler gibi.
Bu ayrıca şu anlama da geliyor, bir çok durumda requestten gelen objeyi **direkt olarak database**'e her şeyi otomatik olarak doğrulanmış bir biçimde aktarabilirisin.
Bu aynı zamanda, birçok durumda request’ten aldığınız nesneyi **doğrudan veritabanına** iletebileceğiniz anlamına gelir; zira her şey otomatik olarak doğrulanır.
Aynı şekilde, databaseden gelen objeyi de **direkt olarak isteğe** de tamamiyle doğrulanmış bir biçimde gönderebilirsiniz.
Tersi yönde de geçerlidir; birçok durumda veritabanından aldığınız nesneyi **doğrudan client**’a gönderebilirsiniz.
**FastAPI** ile beraber **Pydantic**'in bütün özelliklerine sahip olacaksınız (FastAPI data kontrolünü Pydantic'in üzerine kurduğu için):
**FastAPI** ile **Pydantic**’in tüm özelliklerini elde edersiniz (FastAPI, tüm veri işlemede Pydantic’e dayanır):
* **Kafa karıştırmaz**:
* Farklı bir syntax öğrenmenize gerek kalmaz,
* Eğer Python typelarını nasıl kullanacağını biliyorsan Pydantic kullanmayı da biliyorsundur.
* Kullandığın geliştirme araçları ile iyi çalışır **<abbrtitle="Integrated Development Environment, kod editörüne benzer">IDE</abbr>/<abbrtitle="Code errorlarınızı inceleyen program">linter</abbr>/brain**:
* Pydantic'in veri yapıları aslında sadece senin tanımladığın classlar; Bu yüzden doğrulanmış dataların ile otomatik tamamlama, linting ve mypy'ı kullanarak sorunsuz bir şekilde çalışabilirsin
* **En kompleks** yapıları bile doğrula:
* Hiyerarşik Pydantic modellerinin kullanımı ile beraber, Python `typing`’s `List` and `Dict`, vs gibi şeyleri doğrula.
* Doğrulayıcılar en kompleks data şemalarının bile temiz ve kolay bir şekilde tanımlanmasına izin veriyor, ve hepsi JSON şeması olarak dokümante ediliyor
* Pydantic, JSON objen ne kadar derin (nested) olursa olsun doğrulamasını ve gösterimini yapıyor
* Öğrenmeniz gereken yeni bir şema tanımlama mikro-dili yok.
* Python type’larını biliyorsanız Pydantic’i nasıl kullanacağınızı da biliyorsunuz.
* **<abbrtitle="Integrated Development Environment - Tümleşik Geliştirme Ortamı: bir kod editörüne benzer">IDE</abbr>/<dfntitle="koddaki hataları denetleyen bir program">linter</dfn>/beyin**’inizle iyi anlaşır:
* Pydantic veri yapıları, sizin tanımladığınız sınıfların örnekleridir; bu nedenle doğrulanmış verilerinizle otomatik tamamlama, linting ve mypy sorunsuz çalışır, sezgileriniz de yol gösterir.
* **Karmaşık yapıları** doğrulayın:
* Hiyerarşik Pydantic modelleri, Python `typing`’in `List` ve `Dict`’i vb. kullanımı.
* Doğrulayıcılar (validators), karmaşık veri şemalarının net ve kolay şekilde tanımlanmasını, kontrol edilmesini ve JSON Schema olarak dokümante edilmesini sağlar.
* Derinlemesine iç içe **JSON** nesnelerine sahip olabilir, hepsinin doğrulanmasını ve anotasyonlanmasını sağlayabilirsiniz.
* **Genişletilebilir**:
* Pydantic özelleştirilmiş data tiplerinin tanımlanmasının yapılmasına izin veriyor ayrıca validator decoratorü ile senin doğrulamaları genişletip, kendi doğrulayıcılarını yazmana izin veriyor.
* 100% test kapsayıcılığı.
* Pydantic, özel veri tiplerinin tanımlanmasına izin verir; ayrıca validator decorator’üyle bir modeldeki metodlarla doğrulamayı genişletebilirsiniz.
@ -44,7 +44,7 @@ Sonrasında, (**FastAPI** kullanan bir geliştirici olarak) sahip olmak istediğ
Çeşitli fikirleri en popüler Python editörlerinde test ettim: PyCharm, VS Code, Jedi tabanlı editörler.
Bu test, en son <ahref="https://www.jetbrains.com/research/python-developers-survey-2018/#development-tools"class="external-link"target="_blank">Python Developer Survey</a>'ine göre, kullanıcıların yaklaşık %80'inin kullandığı editörleri kapsıyor.
Bu test, en son <ahref="https://www.jetbrains.com/research/python-developers-survey-2018/#development-tools"class="external-link"target="_blank">Python Geliştirici Anketi</a>'ine göre, kullanıcıların yaklaşık %80'inin kullandığı editörleri kapsıyor.
Bu da demek oluyor ki **FastAPI**, Python geliştiricilerinin %80'inin kullandığı editörlerle test edildi. Ve diğer editörlerin çoğu benzer şekilde çalıştığından, avantajları neredeyse tüm editörlerde çalışacaktır.
## Diğer Swagger UI Parametreleri { #other-swagger-ui-parameters }
Kullanabileceğiniz diğer tüm olası yapılandırmaları görmek için, resmi <ahref="https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/"class="external-link"target="_blank">Swagger UI parametreleri dokümantasyonunu</a> okuyun.
## Yalnızca JavaScript ayarları { #javascript-only-settings }
## Yalnızca JavaScript Ayarları { #javascript-only-settings }
Swagger UI ayrıca bazı yapılandırmaların **yalnızca JavaScript** nesneleri olmasına izin verir (örneğin JavaScript fonksiyonları).
@ -14,7 +14,7 @@ Döndürmeniz gerekenden daha fazla veri döndürmediğinizden emin olmak için,
*path operation*'larınıza özet ve açıklama eklemek ve bunları dokümantasyon arayüzünde göstermek için, [Tutorial - Path Operation Configurations - Summary and Description](../tutorial/path-operation-configuration.md#summary-and-description){.internal-link target=_blank} dokümantasyonunu okuyun.
Strawberry hakkında daha fazlasını <ahref="https://strawberry.rocks/"class="external-link"target="_blank">Strawberry dokümantasyonunda</a> öğrenebilirsiniz.
@ -8,6 +8,6 @@ Projeniz için ilginç ve yararlı görünen bir şey varsa devam edin ve incele
/// tip | İpucu
**FastAPI**'ı yapılandırılmış bir şekilde (önerilir) **öğrenmek** istiyorsanız bunun yerine [Öğretici - Kullanıcı Rehberi](../tutorial/index.md){.internal-link target=_blank}'ni bölüm bölüm okuyun.
**FastAPI**'yi yapılandırılmış bir şekilde (önerilir) **öğrenmek** istiyorsanız bunun yerine [Öğretici - Kullanıcı Rehberi](../tutorial/index.md){.internal-link target=_blank}'ni bölüm bölüm okuyun.
* **Hızlı**: Çok yüksek performanslı, **NodeJS** ve **Go** ile eşit düzeyde (Starlette ve Pydantic sayesinde). [Mevcut en hızlı Python framework'lerinden biri](#performance).
* **Kodlaması Hızlı**: Özellik geliştirme hızını yaklaşık %200 ile %300 aralığında artırır. *
* **Daha az hata**: İnsan (geliştirici) kaynaklı hataları yaklaşık %40 azaltır. *
* **Sezgisel**: Harika bir editör desteği. Her yerde <abbrtitle="auto-complete, autocompletion, IntelliSense olarak da bilinir">Completion</abbr>. Hata ayıklamaya daha az zaman.
* **Sezgisel**: Harika bir editör desteği. Her yerde <dfntitle="oto-tamamlama, autocompletion, IntelliSense olarak da bilinir">Tamamlama</dfn>. Hata ayıklamaya daha az zaman.
* **Kolay**: Kullanımı ve öğrenmesi kolay olacak şekilde tasarlandı. Doküman okumaya daha az zaman.
* **Kısa**: Kod tekrarını minimize eder. Her parametre tanımından birden fazla özellik. Daha az hata.
* **Sağlam**: Production'a hazır kod elde edersiniz. Otomatik etkileşimli dokümantasyon ile birlikte.
Web API yerine terminalde kullanılacak bir <abbrtitle="Command Line Interface">CLI</abbr> uygulaması geliştiriyorsanız <ahref="https://typer.tiangolo.com/"class="external-link"target="_blank">**Typer**</a>'a göz atın.
Web API yerine terminalde kullanılacak bir <abbrtitle="Command Line Interface - Komut Satırı Arayüzü">CLI</abbr> uygulaması geliştiriyorsanız <ahref="https://typer.tiangolo.com/"class="external-link"target="_blank">**Typer**</a>'a göz atın.
**Typer**, FastAPI'ın küçük kardeşi. Ve hedefi CLI'ların **FastAPI'ı** olmak. ⌨️ 🚀
@ -368,7 +368,7 @@ item: Item
* Verinin doğrulanması:
* Veri geçersiz olduğunda otomatik ve anlaşılır hatalar.
* Çok derin iç içe JSON nesneleri için bile doğrulama.
* Girdi verisinin <abbrtitle="serialization, parsing, marshalling olarak da bilinir">Dönüşümü</abbr>: network'ten gelen veriyi Python verisine ve type'larına çevirir. Şunlardan okur:
* Girdi verisinin <dfntitle="şöyle de bilinir: serileştirme, ayrıştırma, marshalling">Dönüşümü</dfn>: network'ten gelen veriyi Python verisine ve type'larına çevirir. Şunlardan okur:
* JSON.
* Path parameter'lar.
* Query parameter'lar.
@ -376,7 +376,7 @@ item: Item
* Header'lar.
* Form'lar.
* File'lar.
* Çıktı verisinin <abbrtitle="serialization, parsing, marshalling olarak da bilinir">Dönüşümü</abbr>: Python verisini ve type'larını network verisine çevirir (JSON olarak):
* Çıktı verisinin <dfntitle="şöyle de bilinir: serileştirme, ayrıştırma, marshalling">Dönüşümü</dfn>: Python verisini ve type'larını network verisine çevirir (JSON olarak):
@ -439,7 +439,7 @@ Daha fazla özellik içeren daha kapsamlı bir örnek için <a href="https://fas
* **parameter**'ların farklı yerlerden: **header**'lar, **cookie**'ler, **form alanları** ve **file**'lar olarak tanımlanması.
* `maximum_length` ya da `regex` gibi **doğrulama kısıtlamalarının** nasıl ayarlanacağı.
* Çok güçlü ve kullanımı kolay bir **<abbrtitle="components, resources, providers, services, injectables olarak da bilinir">Dependency Injection</abbr>** sistemi.
* Çok güçlü ve kullanımı kolay bir **<dfntitle="şöyle de bilinir: bileşenler, kaynaklar, sağlayıcılar, servisler, enjekte edilebilirler">Bağımlılık Enjeksiyonu</dfn>** sistemi.
* **JWT tokens** ve **HTTP Basic** auth ile **OAuth2** desteği dahil güvenlik ve kimlik doğrulama.
* **Çok derin iç içe JSON modelleri** tanımlamak için daha ileri (ama aynı derecede kolay) teknikler (Pydantic sayesinde).
* <ahref="https://strawberry.rocks"class="external-link"target="_blank">Strawberry</a> ve diğer kütüphaneler ile **GraphQL** entegrasyonu.
@ -524,7 +524,7 @@ Starlette tarafından kullanılanlar:
* <ahref="https://github.com/Kludex/python-multipart"target="_blank"><code>python-multipart</code></a> - `request.form()` ile, form <abbrtitle="HTTP request'inden gelen string'i Python verisine dönüştürme">"parsing"</abbr> desteği istiyorsanız gereklidir.
* <ahref="https://github.com/Kludex/python-multipart"target="_blank"><code>python-multipart</code></a> - `request.form()` ile, form <dfntitle="HTTP request'ten gelen string'i Python verisine dönüştürme">"ayrıştırma"</dfn> desteği istiyorsanız gereklidir.
FastAPI tarafından kullanılanlar:
@ -534,7 +534,7 @@ FastAPI tarafından kullanılanlar:
### `standard` Bağımlılıkları Olmadan { #without-standard-dependencies }
`standard` opsiyonel bağımlılıklarını dahil etmek istemiyorsanız, `pip install "fastapi[standard]"` yerine `pip install fastapi` ile kurabilirsiniz.
`standard` opsiyonel bağımlılıklarını dahil etmek istemiyorsanız, `pip install fastapi` ile kurabilirsiniz.
### `fastapi-cloud-cli` Olmadan { #without-fastapi-cloud-cli }
Python, isteğe bağlı "type hints" (diğer adıyla "type annotations") desteğine sahiptir.
Bu **"type hints"** veya annotations, bir değişkenin <abbrtitle="örneğin: str, int, float, bool">type</abbr>'ını bildirmeye yarayan özel bir sözdizimidir.
Bu **"type hints"** veya annotations, bir değişkenin <dfntitle="örneğin: str, int, float, bool">tip</dfn>'ini bildirmeye yarayan özel bir sözdizimidir.
Değişkenleriniz için type bildirerek, editörler ve araçlar size daha iyi destek sağlayabilir.
Değişkenleriniz için tip bildirerek, editörler ve araçlar size daha iyi destek sağlayabilir.
Bu, Python type hints hakkında sadece **hızlı bir eğitim / bilgi tazeleme** dokümanıdır. **FastAPI** ile kullanmak için gereken minimum bilgiyi kapsar... ki aslında bu çok azdır.
@ -22,7 +22,7 @@ Eğer bir Python uzmanıysanız ve type hints hakkında her şeyi zaten biliyors
* `title()` ile her birinin ilk harfini büyük harfe çevirir.
* Ortada bir boşluk olacak şekilde <abbrtitle="Hepsini, tek bir bütün olacak şekilde bir araya koyar. İçerikler ardışık şekilde yer alır.">Concatenates</abbr> eder.
* Ortada bir boşluk olacak şekilde <dfntitle="Onları tek bir bütün olarak bir araya getirir. İçerikler art arda gelir.">Birleştirir</dfn>.
### Tip parametreleri ile Generic tipler { #generic-types-with-type-parameters }
### `typing` modülü { #typing-module }
`dict`, `list`, `set` ve `tuple` gibi, başka değerler içerebilen bazı veri yapıları vardır. Ve iç değerlerin kendi tipi de olabilir.
Bazı ek kullanım durumları için standart kütüphanedeki `typing` modülünden bazı şeyleri import etmeniz gerekebilir. Örneğin bir şeyin "herhangi bir tip" olabileceğini bildirmek istediğinizde, `typing` içindeki `Any`'yi kullanabilirsiniz:
İç tipleri olan bu tiplere "**generic**" tipler denir. Ve bunları, iç tipleriyle birlikte bildirmek mümkündür.
```python
from typing import Any
Bu tipleri ve iç tipleri bildirmek için standart Python modülü `typing`'i kullanabilirsiniz. Bu modül, özellikle bu type hints desteği için vardır.
#### Python'un daha yeni sürümleri { #newer-versions-of-python }
`typing` kullanan sözdizimi, Python 3.6'dan en yeni sürümlere kadar (Python 3.9, Python 3.10, vb. dahil) tüm sürümlerle **uyumludur**.
def some_function(data: Any):
print(data)
```
Python geliştikçe, **daha yeni sürümler** bu type annotations için daha iyi destekle gelir ve çoğu durumda type annotations bildirmek için `typing` modülünü import edip kullanmanız bile gerekmez.
### Generic tipler { #generic-types }
Projeniz için daha yeni bir Python sürümü seçebiliyorsanız, bu ek sadelikten yararlanabilirsiniz.
Bazı tipler, köşeli parantez içinde "type parameters" alarak iç tiplerini tanımlayabilir; örneğin "string listesi" `list[str]` olarak bildirilir.
Tüm dokümanlarda her Python sürümüyle uyumlu örnekler vardır (fark olduğunda).
Bu şekilde type parameter alabilen tiplere **Generic types** veya **Generics** denir.
Örneğin "**Python 3.6+**", Python 3.6 veya üstüyle (3.7, 3.8, 3.9, 3.10, vb. dahil) uyumludur. "**Python 3.9+**" ise Python 3.9 veya üstüyle (3.10 vb. dahil) uyumludur.
Aynı builtin tipleri generics olarak kullanabilirsiniz (köşeli parantez ve içinde tiplerle):
Eğer **Python'un en güncel sürümlerini** kullanabiliyorsanız, en güncel sürüme ait örnekleri kullanın; bunlar **en iyi ve en basit sözdizimine** sahip olur, örneğin "**Python 3.10+**".
* `list`
* `tuple`
* `set`
* `dict`
#### List { #list }
@ -163,11 +166,11 @@ Eğer **Python'un en güncel sürümlerini** kullanabiliyorsanız, en güncel s
Değişkeni, aynı iki nokta (`:`) sözdizimiyle bildirin.
Type olarak `list` yazın.
Tip olarak `list` yazın.
`list`, bazı iç tipleri barındıran bir tip olduğundan, bunları köşeli parantez içine yazarsınız:
Bir değişkenin **birkaç tipten herhangi biri** olabileceğini bildirebilirsiniz; örneğin bir `int` veya bir `str`.
Python 3.6 ve üzeri sürümlerde (Python 3.10 dahil), `typing` içinden `Union` tipini kullanabilir ve köşeli parantez içine kabul edilecek olası tipleri yazabilirsiniz.
Python 3.10'da ayrıca, olası tipleri <abbrtitle='also called "bitwise or operator", but that meaning is not relevant here'>vertical bar (`|`)</abbr> ile ayırabildiğiniz **yeni bir sözdizimi** de vardır.
Bunu tanımlamak için, her iki tipi ayırmak üzere <dfntitle='başka adıyla "bit düzeyinde veya operatörü", ancak burada o anlamı önemli değil'>dikey çizgi (`|`)</dfn> kullanırsınız.
//// tab | Python 3.10+
Buna "union" denir, çünkü değişken bu iki tip kümesinin birleşimindeki herhangi bir şey olabilir.
Sadece `str` yerine `Optional[str]` kullanmak, aslında değer `None` olabilecekken her zaman `str` olduğunu varsaydığınız hataları editörün yakalamanıza yardımcı olmasını sağlar.
`Optional[Something]`, aslında `Union[Something, None]` için bir kısayoldur; eşdeğerdirler.
Bu aynı zamanda Python 3.10'da `Something | None` kullanabileceğiniz anlamına gelir:
//// tab | Python 3.10+
```Python hl_lines="1"
@ -266,96 +245,7 @@ Bu aynı zamanda Python 3.10'da `Something | None` kullanabileceğiniz anlamına
#### `Union` veya `Optional` kullanmak { #using-union-or-optional }
Python sürümünüz 3.10'un altındaysa, benim oldukça **öznel** bakış açıma göre küçük bir ipucu:
* 🚨 `Optional[SomeType]` kullanmaktan kaçının
* Bunun yerine ✨ **`Union[SomeType, None]` kullanın** ✨.
İkisi eşdeğerdir ve altta aynı şeydir; ama ben `Optional` yerine `Union` önermeyi tercih ederim. Çünkü "**optional**" kelimesi değerin optional olduğunu ima ediyor gibi durur; ama gerçekte anlamı "değer `None` olabilir"dir. Değer optional olmasa ve hâlâ required olsa bile.
Bence `Union[SomeType, None]` ne anlama geldiğini daha açık şekilde ifade ediyor.
Bu, tamamen kelimeler ve isimlendirmelerle ilgili. Ancak bu kelimeler, sizin ve ekip arkadaşlarınızın kod hakkında nasıl düşündüğünü etkileyebilir.
`name` parametresi `Optional[str]` olarak tanımlanmış, ama **optional değil**; parametre olmadan fonksiyonu çağıramazsınız:
```Python
say_hi() # Oh, no, this throws an error! 😱
```
`name` parametresi **hâlâ required**'dır (*optional* değildir) çünkü bir default değeri yoktur. Yine de `name`, değer olarak `None` kabul eder:
```Python
say_hi(name=None) # This works, None is valid 🎉
```
İyi haber şu ki, Python 3.10'a geçtiğinizde bununla uğraşmanız gerekmeyecek; çünkü tiplerin union'larını tanımlamak için doğrudan `|` kullanabileceksiniz:
Ve böylece `Optional` ve `Union` gibi isimlerle de uğraşmanız gerekmeyecek. 😎
#### Generic tipler { #generic-types }
Köşeli parantez içinde type parameter alan bu tiplere **Generic types** veya **Generics** denir, örneğin:
//// tab | Python 3.10+
Aynı builtin tipleri generics olarak kullanabilirsiniz (köşeli parantez ve içindeki tiplerle):
* `list`
* `tuple`
* `set`
* `dict`
Ve önceki Python sürümlerinde olduğu gibi `typing` modülünden:
* `Union`
* `Optional`
* ...and others.
Python 3.10'da, `Union` ve `Optional` generics'lerini kullanmaya alternatif olarak, tip union'larını bildirmek için <abbrtitle='also called "bitwise or operator", but that meaning is not relevant here'>vertical bar (`|`)</abbr> kullanabilirsiniz; bu çok daha iyi ve daha basittir.
////
//// tab | Python 3.9+
Aynı builtin tipleri generics olarak kullanabilirsiniz (köşeli parantez ve içindeki tiplerle):
* `list`
* `tuple`
* `set`
* `dict`
Ve `typing` modülünden gelen generics:
* `Union`
* `Optional`
* ...and others.
////
Sadece `str` yerine `str | None` kullanmak, aslında değer `None` olabilecekken her zaman `str` olduğunu varsaydığınız hataları editörün yakalamanıza yardımcı olur.
### Tip olarak sınıflar { #classes-as-types }
@ -363,11 +253,11 @@ Bir sınıfı da bir değişkenin tipi olarak bildirebilirsiniz.
@ -401,21 +291,15 @@ Daha fazlasını öğrenmek için <a href="https://docs.pydantic.dev/" class="ex
**FastAPI** tamamen Pydantic üzerine kuruludur.
Bunların pratikte nasıl çalıştığını [Tutorial - User Guide](tutorial/index.md){.internal-link target=_blank} içinde çok daha fazla göreceksiniz.
/// tip | İpucu
Pydantic, default value olmadan `Optional` veya `Union[Something, None]` kullandığınızda özel bir davranışa sahiptir; bununla ilgili daha fazla bilgiyi Pydantic dokümanlarında <ahref="https://docs.pydantic.dev/2.3/usage/models/#required-fields"class="external-link"target="_blank">Required Optional fields</a> bölümünde okuyabilirsiniz.
///
Bunların pratikte nasıl çalıştığını [Eğitim - Kullanım Kılavuzu](tutorial/index.md){.internal-link target=_blank} içinde çok daha fazla göreceksiniz.
## Metadata Annotations ile Type Hints { #type-hints-with-metadata-annotations }
Python'da ayrıca, `Annotated` kullanarak bu type hints içine **ek <abbr title="Veri hakkında veri; bu durumda type hakkında bilgi, örneğin bir açıklama.">metadata</abbr>** koymayı sağlayan bir özellik de vardır.
Python'da ayrıca, `Annotated` kullanarak bu type hints içine **ek <dfn title="Veri hakkında veri; bu durumda tip hakkında bilgi, örneğin bir açıklama.">üstveri</dfn>** koymayı sağlayan bir özellik de vardır.
Python 3.9'dan itibaren `Annotated`, standart kütüphanenin bir parçasıdır; bu yüzden`typing` içinden import edebilirsiniz.
`Annotated`'ı `typing` içinden import edebilirsiniz.
* **Veriyi dönüştürmek**: request'ten gerekli tipe.
* **Veriyi doğrulamak**: her request'ten gelen veriyi:
* Veri geçersiz olduğunda client'a dönen **otomatik hatalar** üretmek.
* OpenAPI kullanarak API'yi **dokümante etmek**:
* bu, daha sonra otomatik etkileşimli dokümantasyon kullanıcı arayüzleri tarafından kullanılır.
Bunların hepsi kulağa soyut gelebilir. Merak etmeyin. Tüm bunları [Tutorial - User Guide](tutorial/index.md){.internal-link target=_blank} içinde çalışırken göreceksiniz.
Bunların hepsi kulağa soyut gelebilir. Merak etmeyin. Tüm bunları [Eğitim - Kullanım Kılavuzu](tutorial/index.md){.internal-link target=_blank} içinde çalışırken göreceksiniz.
Önemli olan, standart Python tiplerini tek bir yerde kullanarak (daha fazla sınıf, decorator vb. eklemek yerine), **FastAPI**'nin sizin için işin büyük kısmını yapmasıdır.
@ -4,7 +4,7 @@ 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âyı daha iyi yönlendirmemize yardımcı olarak](https://fastapi.tiangolo.com/tr/contributing/#translations) bu çeviriyi iyileştirebilirsiniz.
[Yapay zekâ LLM'ini daha iyi yönlendirmemize yardımcı olarak](https://fastapi.tiangolo.com/tr/contributing/#translations) bu çeviriyi iyileştirebilirsiniz.
@ -305,13 +305,13 @@ Normal şekilde bir `FastAPI` class’ı oluşturursunuz.
Hatta her `APIRouter` için olan dependency’lerle birleştirilecek [global dependencies](dependencies/global-dependencies.md){.internal-link target=_blank} bile tanımlayabilirsiniz:
`app/routers/users.py` ve `app/routers/items.py` dosyaları aynı Python package’i olan `app`’in parçası olan submodule’ler olduğu için, onları "relative import" ile tek bir nokta `.` kullanarak import edebiliriz.
@ -374,13 +374,13 @@ from .routers.users import router
Bu yüzden ikisini de aynı dosyada kullanabilmek için submodule’leri doğrudan import ediyoruz:
@ -420,13 +420,13 @@ Bu dosyada, kurumunuzun birden fazla proje arasında paylaştığı bazı admin
Bu örnekte çok basit olacak. Ancak kurum içinde başka projelerle paylaşıldığı için, bunu değiştirip `prefix`, `dependencies`, `tags` vs. doğrudan `APIRouter`’a ekleyemediğimizi varsayalım:
Yine de bu `APIRouter`’ı dahil ederken özel bir `prefix` ayarlamak istiyoruz ki tüm *path operation*’ları `/admin` ile başlasın; ayrıca bu projede hâlihazırda kullandığımız `dependencies` ile güvene almak, `tags` ve `responses` eklemek istiyoruz.
Orijinal `APIRouter`’ı değiştirmeden, bu parametreleri `app.include_router()`’a vererek hepsini tanımlayabiliriz:
Böylece orijinal `APIRouter` değişmeden kalır; yani aynı `app/internal/admin.py` dosyasını kurum içindeki diğer projelerle de paylaşmaya devam edebiliriz.
@ -447,7 +447,7 @@ Dolayısıyla örneğin diğer projeler aynı `APIRouter`’ı farklı bir authe
Burada bunu yapıyoruz... sadece yapabildiğimizi göstermek için 🤷:
@ -95,7 +95,7 @@ Yine, sadece bu tanımı yaparak **FastAPI** ile şunları elde edersiniz:
`str`, `int`, `float` vb. normal tekil tiplerin yanında, `str`’den türeyen daha karmaşık tekil tipleri de kullanabilirsiniz.
Tüm seçenekleri görmek için <ahref="https://docs.pydantic.dev/latest/concepts/types/"class="external-link"target="_blank">Pydantic Type Overview</a> sayfasına göz atın. Sonraki bölümde bazı örnekleri göreceksiniz.
Tüm seçenekleri görmek için <ahref="https://docs.pydantic.dev/latest/concepts/types/"class="external-link"target="_blank">Pydantic Türlerine Genel Bakış</a> sayfasına göz atın. Sonraki bölümde bazı örnekleri göreceksiniz.
Örneğin `Image` modelinde bir `url` alanımız olduğuna göre, bunu `str` yerine Pydantic’in `HttpUrl` tipinden bir instance olacak şekilde tanımlayabiliriz:
@ -155,7 +155,7 @@ Fonksiyon parametreleri şu şekilde tanınır:
FastAPI, `q` değerinin zorunlu olmadığını `= None` default değerinden anlayacaktır.
`str | None` (Python 3.10+) veya `Union[str, None]` (Python 3.9+) içindeki `Union`, FastAPI tarafından bu değerin zorunlu olmadığını belirlemek için kullanılmaz; FastAPI bunun zorunlu olmadığını `= None` default değeri olduğu için bilir.
`str | None`, FastAPI tarafından bu değerin zorunlu olmadığını belirlemek için kullanılmaz; FastAPI bunun zorunlu olmadığını `= None` default değeri olduğu için bilir.
Ancak type annotation'larını eklemek, editor'ünüzün size daha iyi destek vermesini ve hataları yakalamasını sağlar.
Birbirleriyle ilişkili bir **cookie** grubunuz varsa, bunları tanımlamak için bir **Pydantic model** oluşturabilirsiniz.
Birbirleriyle ilişkili bir **cookie** grubunuz varsa, bunları tanımlamak için bir **Pydantic model** oluşturabilirsiniz. 🍪
Bu sayede **model'i yeniden kullanabilir**, **birden fazla yerde** tekrar tekrar kullanabilir ve tüm parametreler için validation ve metadata'yı tek seferde tanımlayabilirsiniz.
Bu sayede **model'i yeniden kullanabilir**, **birden fazla yerde** tekrar tekrar kullanabilir ve tüm parametreler için validation ve metadata'yı tek seferde tanımlayabilirsiniz. 😎
/// note | Not
Bu özellik FastAPI `0.115.0` sürümünden beri desteklenmektedir.
This is supported since FastAPI version `0.115.0`. 🤓
///
/// tip | İpucu
Aynı teknik `Query`, `Cookie` ve `Header` için de geçerlidir.
Aynı teknik `Query`, `Cookie` ve `Header` için de geçerlidir. 😎
Bazı özel kullanım senaryolarında (muhtemelen çok yaygın değildir) almak istediğiniz cookie'leri **kısıtlamak** isteyebilirsiniz.
API'niz artık kendi <abbrtitle="This is a joke, just in case. It has nothing to do with cookie consents, but it's funny that even the API can now reject the poor cookies. Have a cookie. 🍪">cookie consent</abbr>'ını kontrol etme gücüne sahip.
API'niz artık kendi <dfntitle="Bu bir şaka, sadece bilginize. Cookie onaylarıyla ilgisi yok, ama API'nin de artık zavallı cookie'leri reddedebilmesi komik. Bir cookie alın. 🍪">cookie onayı</dfn>'nı kontrol etme gücüne sahip. 🤪🍪
Pydantic'in model configuration'ını kullanarak `extra` olan herhangi bir field'ı `forbid` edebilirsiniz:
@ -54,9 +54,9 @@ Pydantic'in model configuration'ını kullanarak `extra` olan herhangi bir field
Bir client **fazladan cookie** göndermeye çalışırsa, bir **error** response alır.
Onayınızı almak için bunca çaba harcayan zavallı cookie banner'ları... <abbrtitle="This is another joke. Don't pay attention to me. Have some coffee for your cookie. ☕">API'nin bunu reddetmesi için</abbr>.
Onayınızı almak için bunca çaba harcayan zavallı cookie banner'ları... <dfntitle="Bu da başka bir şaka. Dikkate almayın. Cookie'niz için biraz kahve alın. ☕">API'nin bunu reddetmesi için</dfn>. 🍪
Örneğin client, değeri `good-list-please` olan bir `santa_tracker` cookie'si göndermeye çalışırsa, client `santa_tracker`<abbrtitle="Santa disapproves the lack of cookies. 🎅 Okay, no more cookie jokes.">cookie is not allowed</abbr> diyen bir **error** response alır:
Örneğin client, değeri `good-list-please` olan bir `santa_tracker` cookie'si göndermeye çalışırsa, client `santa_tracker`<dfntitle="Noel Baba cookie eksikliğini onaylamıyor. 🎅 Tamam, artık cookie şakası yok.">cookie'ye izin verilmiyor</dfn> diyen bir **error** response alır:
```json
{
@ -73,4 +73,4 @@ Onayınızı almak için bunca çaba harcayan zavallı cookie banner'ları... <a
## Özet { #summary }
**FastAPI**'de <abbrtitle="Have a last cookie before you go. 🍪">**cookies**</abbr> tanımlamak için **Pydantic model**'lerini kullanabilirsiniz. 😎
**FastAPI**'de <dfntitle="Gitmeden önce son bir cookie alın. 🍪">**cookie**</dfn> tanımlamak için **Pydantic model**'lerini kullanabilirsiniz. 😎
Ancak **veriyi doldurup** "Execute" düğmesine tıklasanız bile, docs UI **JavaScript** ile çalıştığı için çerezler gönderilmez ve herhangi bir değer yazmamışsınız gibi bir **hata** mesajı görürsünüz.
Ancak **veriyi doldurup** "Execute" düğmesine tıklasanız bile, docs UI **JavaScript** ile çalıştığı için cookie'ler gönderilmez ve herhangi bir değer yazmamışsınız gibi bir **hata** mesajı görürsünüz.
///
## Özet { #recap }
`Query` ve `Path` ile aynı ortak deseni kullanarak, çerezleri `Cookie` ile tanımlayın.
`Query` ve `Path` ile aynı ortak deseni kullanarak, cookie'leri `Cookie` ile tanımlayın.
`CORSMiddleware` implementasyonu tarafından kullanılan varsayılan parametreler kısıtlayıcıdır; bu nedenle tarayıcıların Cross-Domain bağlamında kullanmasına izin vermek için belirli origin’leri, method’ları veya header’ları açıkça etkinleştirmeniz gerekir.
@ -78,7 +78,7 @@ Bu durumda middleware gelen request’i intercept eder ve uygun CORS header’la
## Daha Fazla Bilgi { #more-info }
<abbrtitle="Cross-Origin Resource Sharing">CORS</abbr> hakkında daha fazla bilgi için <ahref="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS"class="external-link"target="_blank">Mozilla CORS dokümantasyonu</a>na bakın.
<abbrtitle="Cross-Origin Resource Sharing - Kökenler Arası Kaynak Paylaşımı">CORS</abbr> hakkında daha fazla bilgi için <ahref="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS"class="external-link"target="_blank">Mozilla CORS dokümantasyonu</a>na bakın.
Bu dependency'ler normal dependency'lerle aynı şekilde çalıştırılır/çözülür. Ancak (eğer bir değer döndürüyorlarsa) bu değer *path operation function*'ınıza aktarılmaz.
@ -44,13 +44,13 @@ Normalde kullandığınız aynı dependency *function*'larını burada da kullan
Request gereksinimleri (header'lar gibi) veya başka alt dependency'ler tanımlayabilirler:
@ -58,7 +58,7 @@ Ayrıca değer döndürebilirler ya da döndürmeyebilirler; dönen değer kulla
Yani başka bir yerde zaten kullandığınız, değer döndüren normal bir dependency'yi tekrar kullanabilirsiniz; değer kullanılmasa bile dependency çalıştırılacaktır:
# `yield` ile Dependency'ler { #dependencies-with-yield }
FastAPI, işini bitirdikten sonra <abbrtitle='bazen "exit code", "cleanup code", "teardown code", "closing code", "context manager exit code" vb. olarak da adlandırılır'>ek adımlar çalıştıran</abbr> dependency'leri destekler.
FastAPI, işini bitirdikten sonra <dfntitle='bazen "exit code", "cleanup code", "teardown code", "closing code", "context manager exit code" vb. olarak da adlandırılır'>ek adımlar</dfn> çalıştıran dependency'leri destekler.
Bunu yapmak için `return` yerine `yield` kullanın ve ek adımları (kodu) `yield` satırından sonra yazın.
/// tip | İpucu
Her dependency için yalnızca **bir kez**`yield` kullandığınızdan emin olun.
Her dependency için yalnızca bir kez `yield` kullandığınızdan emin olun.
///
@ -29,15 +29,15 @@ Hatta FastAPI bu iki decorator'ı içeride (internally) kullanır.
Response oluşturulmadan önce yalnızca `yield` satırına kadar olan (ve `yield` dahil) kod çalıştırılır:
Exception yakalayıp buna göre özel bir response oluşturmak istiyorsanız bir [Custom Exception Handler](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} oluşturun.
@ -117,7 +117,7 @@ Exception yakalayıp buna göre özel bir response oluşturmak istiyorsanız bir
`yield` kullanan bir dependency içinde `except` ile bir exception yakalar ve bunu tekrar fırlatmazsanız (ya da yeni bir exception fırlatmazsanız), FastAPI normal Python'da olduğu gibi bir exception olduğunu fark edemez:
Bu durumda client, biz `HTTPException` veya benzeri bir şey fırlatmadığımız için olması gerektiği gibi *HTTP 500 Internal Server Error* response'u görür; ancak server **hiç log üretmez** ve hatanın ne olduğuna dair başka bir işaret de olmaz. 😱
@ -127,7 +127,7 @@ Bu durumda client, biz `HTTPException` veya benzeri bir şey fırlatmadığımı
Aynı exception'ı `raise` ile tekrar fırlatabilirsiniz:
Ama *path operation function*'dan döndükten sonra dependency'yi kullanmayacağınızı biliyorsanız, `Depends(scope="function")` kullanarak FastAPI'ye dependency'yi *path operation function* döndükten sonra kapatmasını, ancak **response gönderilmeden önce** kapatmasını söyleyebilirsiniz.
`Depends()` şu değerleri alabilen bir `scope` parametresi alır:
@ -234,7 +234,6 @@ participant operation as Path Operation
`yield` kullanan dependency'ler, zaman içinde farklı kullanım senaryolarını kapsamak ve bazı sorunları düzeltmek için gelişti.
FastAPI'nin farklı sürümlerinde nelerin değiştiğini görmek isterseniz, advanced guide'da şu bölümü okuyabilirsiniz: [Advanced Dependencies - Dependencies with `yield`, `HTTPException`, `except` and Background Tasks](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks){.internal-link target=_blank}.
Ayrıca dependency fonksiyonunun içinde `with` veya `async with` ifadeleri kullanarak **FastAPI**'de `yield` kullanan dependency'lerin içinde de kullanabilirsiniz:
Ve [*path operation decorator*'larına `dependencies` ekleme](dependencies-in-path-operation-decorators.md){.internal-link target=_blank} bölümündeki tüm fikirler hâlâ geçerlidir; ancak bu sefer, uygulamadaki tüm *path operation*'lar için geçerli olur.
**FastAPI**, çok güçlü ama aynı zamanda sezgisel bir **<abbrtitle="also known as components, resources, providers, services, injectables">Dependency Injection</abbr>** sistemine sahiptir.
**FastAPI**, çok güçlü ama aynı zamanda sezgisel bir **<dfntitle="diğer adları: components, resources, providers, services, injectables">Bağımlılık Enjeksiyonu</dfn>** sistemine sahiptir.
Kullanımı çok basit olacak şekilde tasarlanmıştır ve herhangi bir geliştiricinin diğer bileşenleri **FastAPI** ile entegre etmesini kolaylaştırır.
Bağımlılıklarınızdan biri aynı *path operation* için birden fazla kez tanımlanırsa (örneğin birden fazla bağımlılığın ortak bir alt bağımlılığı varsa), **FastAPI** o alt bağımlılığı request başına yalnızca bir kez çağıracağını bilir.
Dönen değeri bir <abbrtitle="A utility/system to store computed/generated values, to reuse them instead of computing them again. - Hesaplanan/üretilen değerleri saklayıp, onları tekrar hesaplamak yerine yeniden kullanmayı sağlayan bir yardımcı araç/sistem.">"cache"</abbr> içinde saklar ve aynı request içinde buna ihtiyaç duyan tüm "dependant"lara aktarır; böylece aynı request için bağımlılığı tekrar tekrar çağırmaz.
Dönen değeri bir <dfntitle="Hesaplanan/üretilen değerleri saklayıp, tekrar hesaplamak yerine yeniden kullanmayı sağlayan bir yardımcı araç/sistem.">"önbellek"</dfn> içinde saklar ve aynı request içinde buna ihtiyaç duyan tüm "dependant"lara aktarır; böylece aynı request için bağımlılığı tekrar tekrar çağırmaz.
Daha ileri bir senaryoda, "cached" değeri kullanmak yerine aynı request içinde her adımda (muhtemelen birden fazla kez) bağımlılığın çağrılması gerektiğini biliyorsanız, `Depends` kullanırken `use_cache=False` parametresini ayarlayabilirsiniz:
@ -23,32 +23,32 @@ Kullanabileceğiniz ek veri tiplerinden bazıları şunlardır:
* `UUID`:
* Birçok veritabanı ve sistemde ID olarak yaygın kullanılan, standart bir "Universally Unique Identifier".
* request ve response'larda `str` olarak temsil edilir.
* request'lerde ve response'larda `str` olarak temsil edilir.
* `datetime.datetime`:
* Python `datetime.datetime`.
* request ve response'larda ISO 8601 formatında bir `str` olarak temsil edilir, örn: `2008-09-15T15:53:00+05:00`.
* request'lerde ve response'larda ISO 8601 formatında bir `str` olarak temsil edilir, örn: `2008-09-15T15:53:00+05:00`.
* `datetime.date`:
* Python `datetime.date`.
* request ve response'larda ISO 8601 formatında bir `str` olarak temsil edilir, örn: `2008-09-15`.
* request'lerde ve response'larda ISO 8601 formatında bir `str` olarak temsil edilir, örn: `2008-09-15`.
* `datetime.time`:
* Python `datetime.time`.
* request ve response'larda ISO 8601 formatında bir `str` olarak temsil edilir, örn: `14:23:55.003`.
* request'lerde ve response'larda ISO 8601 formatında bir `str` olarak temsil edilir, örn: `14:23:55.003`.
* `datetime.timedelta`:
* Python `datetime.timedelta`.
* request ve response'larda toplam saniye sayısını ifade eden bir `float` olarak temsil edilir.
* request'lerde ve response'larda toplam saniye sayısını ifade eden bir `float` olarak temsil edilir.
* Pydantic, bunu ayrıca bir "ISO 8601 time diff encoding" olarak temsil etmeye de izin verir, daha fazla bilgi için <ahref="https://docs.pydantic.dev/latest/concepts/serialization/#custom-serializers"class="external-link"target="_blank">dokümanlara bakın</a>.
* `frozenset`:
* request ve response'larda, `set` ile aynı şekilde ele alınır:
* request'lerde ve response'larda, `set` ile aynı şekilde ele alınır:
* request'lerde bir list okunur, tekrarlar kaldırılır ve `set`'e dönüştürülür.
* response'larda `set`, `list`'e dönüştürülür.
* Üretilen schema, `set` değerlerinin benzersiz olduğunu belirtir (JSON Schema'nın `uniqueItems` özelliğini kullanarak).
* `bytes`:
* Standart Python `bytes`.
* request ve response'larda `str` gibi ele alınır.
* request'lerde ve response'larda `str` gibi ele alınır.
* Üretilen schema, bunun `binary` "format"ına sahip bir `str` olduğunu belirtir.
* `Decimal`:
* Standart Python `Decimal`.
* request ve response'larda `float` ile aynı şekilde işlenir.
* request'lerde ve response'larda `float` ile aynı şekilde işlenir.
* Geçerli tüm Pydantic veri tiplerini burada görebilirsiniz: <ahref="https://docs.pydantic.dev/latest/usage/types/types/"class="external-link"target="_blank">Pydantic data types</a>.
@ -8,7 +8,7 @@ Bu durum özellikle kullanıcı modellerinde sık görülür, çünkü:
* **output modeli**`password` içermemelidir.
* **database modeli** büyük ihtimalle hash'lenmiş bir `password` tutmalıdır.
/// danger
/// danger | 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.
@ -132,7 +132,7 @@ UserInDB(
)
```
/// warning
/// warning | Uyarı
Ek destek fonksiyonları olan `fake_password_hasher` ve `fake_save_user` sadece verinin olası bir akışını göstermek içindir; elbette gerçek bir güvenlik sağlamazlar.
@ -164,7 +164,7 @@ OpenAPI'de bu `anyOf` ile tanımlanır.
Bunu yapmak için standart Python type hint'i olan <ahref="https://docs.python.org/3/library/typing.html#typing.Union"class="external-link"target="_blank">`typing.Union`</a>'ı kullanın:
/// note
/// note | Not
Bir <ahref="https://docs.pydantic.dev/latest/concepts/types/#unions"class="external-link"target="_blank">`Union`</a> tanımlarken en spesifik type'ı önce, daha az spesifik olanı sonra ekleyin. Aşağıdaki örnekte daha spesifik olan `PlaneItem`, `Union[PlaneItem, CarItem]` içinde `CarItem`'dan önce gelir.
@ -190,9 +190,9 @@ Ancak bunu `response_model=PlaneItem | CarItem` atamasına koyarsak hata alırı
Aynı şekilde, nesne listesi döndüren response'ları da tanımlayabilirsiniz.
Bunun için standart Python `typing.List`'i (ya da Python 3.9 ve üzeri için sadece `list`) kullanın:
Şimdi şu gibi geçersiz bir item göndermeyi deneyin:
@ -239,6 +239,6 @@ from starlette.exceptions import HTTPException as StarletteHTTPException
Exception’ı, **FastAPI**’nin aynı varsayılan exception handler’larıyla birlikte kullanmak isterseniz, varsayılan exception handler’ları `fastapi.exception_handlers` içinden import edip yeniden kullanabilirsiniz:
Bu örnekte sadece oldukça açıklayıcı bir mesajla hatayı yazdırıyorsunuz; ama fikir anlaşılıyor. Exception’ı kullanıp ardından varsayılan exception handler’ları olduğu gibi yeniden kullanabilirsiniz.
@ -62,7 +62,7 @@ Editörünüzde kullanmak FastAPI'nin avantajlarını gerçekten gösterir: ne k
İlk adım FastAPI'yi kurmaktır.
Bir [virtual environment](../virtual-environments.md){.internal-link target=_blank} oluşturduğunuzdan emin olun, etkinleştirin ve ardından **FastAPI'yi kurun**:
Bir [sanal ortam](../virtual-environments.md){.internal-link target=_blank} oluşturduğunuzdan emin olun, etkinleştirin ve ardından **FastAPI'yi kurun**:
@ -92,4 +92,4 @@ Bu stack davranışı, middleware'lerin öngörülebilir ve kontrol edilebilir b
Diğer middleware'ler hakkında daha fazlasını daha sonra [Advanced User Guide: Advanced Middleware](../advanced/middleware.md){.internal-link target=_blank} bölümünde okuyabilirsiniz.
Bir sonraki bölümde, middleware ile <abbrtitle="Cross-Origin Resource Sharing">CORS</abbr>'un nasıl ele alınacağını göreceksiniz.
Bir sonraki bölümde, middleware ile <abbrtitle="Cross-Origin Resource Sharing - Çapraz Kaynak Paylaşımı">CORS</abbr>'un nasıl ele alınacağını göreceksiniz.
Açıklamalar genelde uzun olur ve birden fazla satıra yayılır; bu yüzden *path operation* açıklamasını, fonksiyonun içinde <abbrtitle="dokümantasyon için, fonksiyon içinde ilk ifade olarak yazılan (herhangi bir değişkene atanmayan) çok satırlı string">docstring</abbr> olarak tanımlayabilirsiniz; **FastAPI** de onu buradan okur.
Açıklamalar genelde uzun olur ve birden fazla satıra yayılır; bu yüzden *path operation* açıklamasını, fonksiyonun içinde <dfntitle="dokümantasyon için kullanılan, fonksiyon içinde ilk ifade olarak yer alan (herhangi bir değişkene atanmayan) çok satırlı string">docstring</dfn> olarak tanımlayabilirsiniz; **FastAPI** de onu buradan okur.
Docstring içinde <ahref="https://en.wikipedia.org/wiki/Markdown"class="external-link"target="_blank">Markdown</a> yazabilirsiniz; doğru şekilde yorumlanır ve gösterilir (docstring girintisi dikkate alınarak).
@ -90,9 +90,9 @@ Bu yüzden siz sağlamazsanız, **FastAPI** otomatik olarak "Successful response
## Bir *path operation*’ı Deprecate Etmek { #deprecate-a-path-operation }
Bir *path operation*’ı kaldırmadan, <abbrtitle="kullanım dışı, kullanılması önerilmez">deprecated</abbr> olarak işaretlemeniz gerekiyorsa `deprecated` parametresini verin:
Bir *path operation*’ı kaldırmadan, <dfntitle="eskimiş, kullanılması önerilmez">deprecated</dfn> olarak işaretlemeniz gerekiyorsa `deprecated` parametresini verin:
Ancak şunu unutmayın: `Annotated` kullanırsanız bu problem olmaz; çünkü `Query()` veya `Path()` için fonksiyon parametresi default değerlerini kullanmıyorsunuz.
## Parametreleri İhtiyacınıza Göre Sıralayın: Küçük Hileler { #order-the-parameters-as-you-need-tricks }
@ -81,15 +81,15 @@ Ancak şunu unutmayın: `Annotated` kullanırsanız bu problem olmaz; çünkü `
Fonksiyonun ilk parametresi olarak `*` geçin.
Python bu `*` ile bir şey yapmaz; ama bundan sonraki tüm parametrelerin keyword argument (anahtar-değer çiftleri) olarak çağrılması gerektiğini bilir; buna <abbrtitle="From: K-ey W-ord Arg-uments"><code>kwargs</code></abbr> da denir. Default değerleri olmasa bile.
Python bu `*` ile bir şey yapmaz; ama bundan sonraki tüm parametrelerin keyword argument (anahtar-değer çiftleri) olarak çağrılması gerektiğini bilir; buna <abbrtitle="Kökeni: K-ey W-ord Arg-uments"><code>kwargs</code></abbr> da denir. Default değerleri olmasa bile.
### `Annotated` ile Daha İyi { #better-with-annotated }
Şunu da unutmayın: `Annotated` kullanırsanız, fonksiyon parametresi default değerlerini kullanmadığınız için bu sorun ortaya çıkmaz ve muhtemelen `*` kullanmanız da gerekmez.
## Sayı Doğrulamaları: `float` Değerler, Büyük ve Küçük { #number-validations-floats-greater-than-and-less-than }
Sayı doğrulamaları `float` değerler için de çalışır.
Burada <abbrtitle="greater than"><code>gt</code></abbr> tanımlayabilmek (sadece <abbrtitle="greater than or equal"><code>ge</code></abbr> değil) önemli hale gelir. Çünkü örneğin bir değerin `0`'dan büyük olmasını isteyebilirsiniz; `1`'den küçük olsa bile.
Burada <abbrtitle="greater than - büyüktür"><code>gt</code></abbr> tanımlayabilmek (sadece <abbrtitle="greater than or equal - büyük veya eşittir"><code>ge</code></abbr> değil) önemli hale gelir. Çünkü örneğin bir değerin `0`'dan büyük olmasını isteyebilirsiniz; `1`'den küçük olsa bile.
Bu durumda `0.5` geçerli bir değer olur. Ancak `0.0` veya `0` geçerli olmaz.
Aynısı <abbrtitle="less than"><code>lt</code></abbr> için de geçerlidir.
Aynısı <abbrtitle="less than - küçüktür"><code>lt</code></abbr> için de geçerlidir.
Python <abbrtitle="String Biçimleme: Format String">string biçimlemede</abbr> kullanılan sözdizimiyle path "parametreleri"ni veya "değişkenleri"ni tanımlayabilirsiniz:
Bu durumda, `item_id` bir `int` olarak tanımlanır.
@ -26,7 +26,7 @@ Bu sayede, fonksiyon içinde hata denetimi, kod tamamlama vb. konularda editör
///
## Veri <abbrtitle="also known as: endpoints, routes">conversion</abbr> { #data-conversion }
## Veri <dfntitle="diğer adlarıyla: serileştirme, ayrıştırma, marshalling">dönüştürme</dfn> { #data-conversion }
Bu örneği çalıştırıp tarayıcınızda <ahref="http://127.0.0.1:8000/items/3"class="external-link"target="_blank">http://127.0.0.1:8000/items/3</a> adresini açarsanız, şöyle bir response görürsünüz:
@ -38,7 +38,7 @@ Bu örneği çalıştırıp tarayıcınızda <a href="http://127.0.0.1:8000/item
Dikkat edin: fonksiyonunuzun aldığı (ve döndürdüğü) değer olan `3`, string `"3"` değil, bir Python `int`'idir.
Yani, bu tip tanımıyla birlikte **FastAPI** size otomatik request <abbrtitle="HTTP isteği ile birlikte gelen string'i Python verisine dönüştürme">"parsing"</abbr> sağlar.
Yani, bu tip tanımıyla birlikte **FastAPI** size otomatik request "<dfntitle="HTTP request'ten gelen string'i Python verisine dönüştürme">ayrıştırma</dfn>" sağlar.
///
@ -118,13 +118,13 @@ Sonra belirli bir kullanıcı hakkında, kullanıcı ID'si ile veri almak için
*Path operation*'lar sırayla değerlendirildiği için, `/users/me` için olan path'in `/users/{user_id}` olandan önce tanımlandığından emin olmanız gerekir:
Merak ediyorsanız: "AlexNet", "ResNet" ve "LeNet", Makine Öğrenmesi <abbrtitle="Technically, Deep Learning model architectures">modelleri</abbr>nin sadece isimleridir.
Merak ediyorsanız: "AlexNet", "ResNet" ve "LeNet", Makine Öğrenmesi <dfntitle="Teknik olarak, Derin Öğrenme model mimarileri">modelleri</dfn>nin sadece isimleridir.
@ -16,7 +16,7 @@ FastAPI, `q`’nun zorunlu olmadığını `= None` varsayılan değerinden anlar
///
## Ek doğrulama { #additional-validation }
## Ek Doğrulama { #additional-validation }
`q` opsiyonel olsa bile, verildiği durumda **uzunluğunun 50 karakteri geçmemesini** zorlayacağız.
@ -47,40 +47,16 @@ Daha eski bir sürüm kullanıyorsanız `Annotated` kullanmaya çalışırken ha
Ş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. 🎉
@ -109,7 +85,7 @@ FastAPI artık şunları yapacak:
## Alternatif (eski): Varsayılan değer olarak `Query` { #alternative-old-query-as-the-default-value }
FastAPI’nin önceki sürümlerinde (<abbrtitle="before 2023-03 - 2023-03’ten ö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.
FastAPI’nin önceki sürümlerinde (<dfntitle="2023-03’ten önce">0.95.0</dfn> ö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.
@ -179,7 +156,7 @@ Fonksiyon parametrelerindeki varsayılan değer stiline göre **`Annotated` kull
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` 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 <ahref="https://typer.tiangolo.com/"class="external-link"target="_blank">Typer</a> gibi başka araçlarla da kullanabilirsiniz. 🚀
@ -191,7 +168,7 @@ Aynı fonksiyonu FastAPI olmadan **başka yerlerde** de **çağırabilirsiniz**
Parametrenin eşleşmesi gereken bir `pattern`<abbrtitle="A regular expression, regex or regexp is a sequence of characters that define a search pattern for strings. - Regular expression (regex/regexp), string’ler için arama deseni tanımlayan karakter dizisidir.">regular expression</abbr> tanımlayabilirsiniz:
Parametrenin eşleşmesi gereken bir `pattern`<dfntitle="String'ler için arama deseni tanımlayan karakter dizisi">düzenli ifade</dfn> tanımlayabilirsiniz:
@ -371,7 +348,7 @@ O zaman bir `alias` tanımlayabilirsiniz; bu alias, parametre değerini bulmak i
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 <abbrtitle="obsolete, recommended not to use it - kullanımdan kalkmış, kullanmamanız önerilir">deprecated</abbr> olarak göstermesini istiyorsunuz.
Bazı client’lar hâlâ kullandığı için bir süre tutmanız gerekiyor, ama dokümanların bunu açıkça <dfntitle="kullanımdan kalkmış, kullanmamanız önerilir">deprecated</dfn> olarak göstermesini istiyorsunuz.
O zaman `Query`’ye `deprecated=True` parametresini geçin:
Örneğin bu custom validator, bir item ID’sinin <abbrtitle="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 <abbrtitle="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 ID’si için `imdb-` ile başladığını kontrol eder:
Örneğin bu custom validator, bir item ID’sinin <abbrtitle="International Standard Book Number - Uluslararası Standart Kitap Numarası">ISBN</abbr> kitap numarası için `isbn-` ile veya <abbrtitle="Internet Movie Database - İnternet Film Veritabanı: filmler hakkında bilgi içeren bir web sitesi">IMDB</abbr> film URL ID’si için `imdb-` ile başladığını kontrol eder:
@ -435,9 +412,9 @@ Fark ettiniz mi? `value.startswith()` ile bir string, tuple alabilir ve tuple i
#### Rastgele Bir Item { #a-random-item }
`data.items()` ile, her dictionary öğesi için key ve value içeren tuple’lardan oluşan bir <abbrtitle="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.
`data.items()` ile, her dictionary öğesi için key ve value içeren tuple’lardan oluşan bir <dfntitle="for döngüsüyle üzerinde gezinebileceğimiz bir şey; list, set vb.">yinelemeli nesne</dfn> elde ederiz.
Bu iterable object’i `list(data.items())` ile düzgün bir `list`’e çeviririz.
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")`.
Fonksiyonda path parametrelerinin parçası olmayan diğer parametreleri tanımladığınızda, bunlar otomatik olarak "query" parametreleri olarak yorumlanır.
`UploadFile` kullanmanın `bytes`’a göre birkaç avantajı vardır:
@ -121,7 +121,7 @@ Formlardan gelen veri, dosya içermiyorsa normalde "media type" olarak `applicat
Ancak form dosya içeriyorsa `multipart/form-data` olarak encode edilir. `File` kullanırsanız, **FastAPI** dosyaları body’nin doğru kısmından alması gerektiğini bilir.
Bu encoding’ler ve form alanları hakkında daha fazla okumak isterseniz <ahref="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST"class="external-link"target="_blank"><abbrtitle="Mozilla Developer Network">MDN</abbr> web dokümanlarındaki <code>POST</code></a> sayfasına bakın.
Bu encoding’ler ve form alanları hakkında daha fazla okumak isterseniz <ahref="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST"class="external-link"target="_blank"><abbrtitle="Mozilla Developer Network - Mozilla Geliştirici Ağı">MDN</abbr> web dokümanlarındaki <code>POST</code></a> sayfasına bakın.
///
@ -143,7 +143,7 @@ Standart type annotation’ları kullanıp varsayılan değeri `None` yaparak bi
Ek metadata ayarlamak için `UploadFile` ile birlikte `File()` da kullanabilirsiniz. Örneğin:
Örneğin OAuth2 spesifikasyonunun kullanılabileceği ("password flow" olarak adlandırılan) yollardan birinde, form alanları olarak bir `username` ve `password` göndermek zorunludur.
<abbrtitle="specification - spesifikasyon">spec</abbr>, alanların adının tam olarak `username` ve `password` olmasını ve JSON değil form alanları olarak gönderilmesini gerektirir.
<dfntitle="spesifikasyon">Spesifikasyon</dfn>, alanların adının tam olarak `username` ve `password` olmasını ve JSON değil form alanları olarak gönderilmesini gerektirir.
`Form` ile `Body` (ve `Query`, `Path`, `Cookie`) ile yaptığınız aynı konfigürasyonları tanımlayabilirsiniz; validasyon, örnekler, alias (örn. `username` yerine `user-name`) vb. dahil.
@ -56,13 +56,13 @@ Formlardan gelen veri normalde "media type" `application/x-www-form-urlencoded`
Ancak form dosyalar içerdiğinde `multipart/form-data` olarak encode edilir. Dosyaları ele almayı bir sonraki bölümde okuyacaksınız.
Bu encoding'ler ve form alanları hakkında daha fazla okumak isterseniz, <ahref="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST"class="external-link"target="_blank"><abbrtitle="Mozilla Developer Network">MDN</abbr> web docs for <code>POST</code></a> sayfasına gidin.
Bu encoding'ler ve form alanları hakkında daha fazla okumak isterseniz, <ahref="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST"class="external-link"target="_blank"><abbrtitle="Mozilla Developer Network - Mozilla Geliştirici Ağı">MDN</abbr> web docs for <code>POST</code></a> sayfasına gidin.
///
/// warning | Uyarı
Bir *path operation* içinde birden fazla `Form` parametresi tanımlayabilirsiniz, ancak JSON olarak almayı beklediğiniz `Body` alanlarını da ayrıca tanımlayamazsınız; çünkü bu durumda request'in body'si `application/json` yerine `application/x-www-form-urlencoded` ile encode edilmiş olur.
Bir *path operation* içinde birden fazla `Form` parametresi tanımlayabilirsiniz, ancak JSON olarak almayı beklediğiniz `Body` alanlarını da ayrıca tanımlayamazsınız; çünkü bu durumda request'in body'si `application/x-www-form-urlencoded` ile encode edilmiş olur.
Bu **FastAPI**'ın bir kısıtlaması değildir, HTTP protokolünün bir parçasıdır.
@ -97,7 +97,7 @@ Artık bir browser password ile user oluşturduğunda, API response içinde ayn
Bu örnekte sorun olmayabilir; çünkü password’ü gönderen kullanıcı zaten aynı kişi.
Ancak aynı modeli başka bir *path operation* için kullanırsak, kullanıcının password’lerini her client’a gönderiyor olabiliriz.
Namun ancak aynı modeli başka bir *path operation* için kullanırsak, kullanıcının password’lerini her client’a gönderiyor olabiliriz.
/// danger
@ -183,7 +183,7 @@ Bazı durumlarda Pydantic field olarak geçerli olmayan bir şey döndürebilir
En yaygın durum, [ileri seviye dokümanlarda daha sonra anlatıldığı gibi doğrudan bir Response döndürmektir](../advanced/response-directly.md){.internal-link target=_blank}.
Bu da çalışır; çünkü `RedirectResponse`, `Response`’un subclass’ıdır ve FastAPI bu basit durumu otomatik olarak yönetir.
@ -201,7 +201,7 @@ Bu da çalışır; çünkü `RedirectResponse`, `Response`’un subclass’ıdı
Ancak geçerli bir Pydantic tipi olmayan başka rastgele bir obje (ör. bir veritabanı objesi) döndürür ve fonksiyonu da öyle annotate ederseniz, FastAPI bu type annotation’dan bir Pydantic response model oluşturmaya çalışır ve başarısız olur.
Aynı şey, farklı tipler arasında bir <abbrtitle='Birden fazla tip arasında union, "bu tiplerden herhangi biri" anlamına gelir.'>union</abbr> kullandığınızda ve bu tiplerden biri veya birkaçı geçerli bir Pydantic tipi değilse de olur; örneğin şu kullanım patlar 💥:
Aynı şey, farklı tipler arasında bir <dfntitle="Birden fazla tip arasındaki bir birleşim, 'bu tiplerden herhangi biri' anlamına gelir.">birleşim</dfn> kullandığınızda ve bu tiplerden biri veya birkaçı geçerli bir Pydantic tipi değilse de olur; örneğin şu kullanım patlar 💥:
Her bir status code hakkında daha fazla bilgi almak ve hangi kodun ne için kullanıldığını görmek için <ahref="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status"class="external-link"target="_blank">HTTP status code'lar hakkında <abbrtitle="Mozilla Developer Network">MDN</abbr> dokümantasyonuna</a> göz atın.
Her bir status code hakkında daha fazla bilgi almak ve hangi kodun ne için kullanıldığını görmek için <ahref="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status"class="external-link"target="_blank"><abbrtitle="Mozilla Developer Network - Mozilla Geliştirici Ağı">MDN</abbr> dokümantasyonu: HTTP status code'lar hakkında</a> göz atın.
///
@ -74,7 +74,7 @@ Her bir status code hakkında daha fazla bilgi almak ve hangi kodun ne için kul
@ -74,7 +74,7 @@ Elbette birden fazla `examples` da geçebilirsiniz:
Bunu yaptığınızda, örnekler bu body verisi için dahili **JSON Schema**’nın bir parçası olur.
Buna rağmen, <abbrtitle="2023-08-26 - bunun yazıldığı tarihte">time of writing this</abbr>, doküman arayüzünü gösteren araç olan Swagger UI, **JSON Schema** içindeki veriler için birden fazla örneği göstermeyi desteklemiyor. Ancak aşağıda bir çözüm yolu var.
Buna rağmen, <dfntitle="2023-08-26">bu yazı yazılırken</dfn>, doküman arayüzünü gösteren araç olan Swagger UI, **JSON Schema** içindeki veriler için birden fazla örneği göstermeyi desteklemiyor. Ancak aşağıda bir çözüm yolu var.
### OpenAPI’ye özel `examples` { #openapi-specific-examples }
@ -132,7 +132,7 @@ Bu durumda bile **FastAPI**, onu oluşturabilmeniz için gereken araçları suna
`OAuth2PasswordBearer` sınıfının bir instance’ını oluştururken `tokenUrl` parametresini veririz. Bu parametre, client’ın (kullanıcının browser’ında çalışan frontend’in) token almak için `username` ve `password` göndereceği URL’yi içerir.
`authenticate_user`, veritabanında var olmayan bir username ile çağrıldığında, yine de sahte (dummy) bir hash'e karşı `verify_password` çalıştırıyoruz.
Bu, username geçerli olsun ya da olmasın endpoint'in yaklaşık aynı sürede yanıt vermesini sağlar; böylece mevcut username'leri saymaya yarayabilecek zamanlama saldırılarını (timing attacks) engeller.
/// note | Not
@ -152,7 +156,7 @@ Response için token endpoint'inde kullanılacak bir Pydantic Model tanımlayın
Yeni bir access token üretmek için bir yardımcı fonksiyon oluşturun.
@ -8,7 +8,7 @@ Burada <a href="https://sqlmodel.tiangolo.com/" class="external-link" target="_b
/// tip | İpucu
İstediğiniz başka bir SQL veya NoSQL veritabanı kütüphanesini kullanabilirsiniz (bazı durumlarda <abbrtitle="Object Relational Mapper: a fancy term for a library where some classes represent SQL tables and instances represent rows in those tables">"ORMs"</abbr> olarak adlandırılır). FastAPI sizi hiçbir şeye zorlamaz.
İstediğiniz başka bir SQL veya NoSQL veritabanı kütüphanesini kullanabilirsiniz (bazı durumlarda <abbrtitle="Object Relational Mapper - Obje-İlişkisel Eşleyici: bazı sınıfların SQL tablolarını ve örneklerin bu tablolardaki satırları temsil ettiği bir kütüphane için süslü bir terim">"ORMs"</abbr> olarak adlandırılır). FastAPI sizi hiçbir şeye zorlamaz. 😎
///
@ -49,7 +49,7 @@ $ pip install sqlmodel
Önce, tek bir **SQLModel** modeliyle uygulamanın en basit ilk sürümünü oluşturacağız.
Aşağıda, **birden fazla model** kullanarak güvenliği ve esnekliği artırıp geliştireceğiz.
Aşağıda, **birden fazla model** kullanarak güvenliği ve esnekliği artırıp geliştireceğiz. 🤓
### Modelleri Oluşturma { #create-models }
@ -93,7 +93,7 @@ Sonra `SQLModel.metadata.create_all(engine)` kullanan bir fonksiyon ekleyerek t
Bir **`Session`**, **nesneleri memory’de** tutar ve verideki gerekli değişiklikleri takip eder; ardından veritabanıyla iletişim kurmak için **`engine` kullanır**.
`yield` ile, her request için yeni bir `Session` sağlayacak bir FastAPI **dependency** oluşturacağız. Bu da her request’te tek session kullanmamızı garanti eder.
`yield` ile, her request için yeni bir `Session` sağlayacak bir FastAPI **dependency** oluşturacağız. Bu da her request’te tek session kullanmamızı garanti eder. 🤓
Ardından bu dependency’yi kullanacak kodun geri kalanını sadeleştirmek için `Annotated` ile `SessionDep` dependency’sini oluştururuz.
@ -107,7 +107,7 @@ Uygulama başlarken veritabanı table’larını oluşturacağız.
Burada bir uygulama startup event’inde table’ları oluşturuyoruz.
Production’da büyük ihtimalle uygulamayı başlatmadan önce çalışan bir migration script’i kullanırsınız.
Production’da büyük ihtimalle uygulamayı başlatmadan önce çalışan bir migration script’i kullanırsınız. 🤓
Şimdi bu uygulamayı biraz **refactor** edelim ve **güvenliği** ile **esnekliği** artıralım.
Önceki uygulamaya bakarsanız, UI’da şu ana kadar client’ın oluşturulacak `Hero`’nun `id` değerini belirlemesine izin verdiğini görebilirsiniz.
Önceki uygulamaya bakarsanız, UI’da şu ana kadar client’ın oluşturulacak `Hero`’nun `id` değerini belirlemesine izin verdiğini görebilirsiniz. 😱
Buna izin vermemeliyiz; DB’de zaten atanmış bir `id`’yi ezebilirler. `id` belirlemek **client** tarafından değil, **backend** veya **veritabanı** tarafından yapılmalıdır.
Ayrıca hero için bir `secret_name` oluşturuyoruz ama şimdiye kadar her yerde geri döndürüyoruz; bu pek de **secret** sayılmaz...
Ayrıca hero için bir `secret_name` oluşturuyoruz ama şimdiye kadar her yerde geri döndürüyoruz; bu pek de **secret** sayılmaz... 😅
Bunları birkaç **ek model** ekleyerek düzelteceğiz. SQLModel’in parlayacağı yer de burası.
Bunları birkaç **ek model** ekleyerek düzelteceğiz. SQLModel’in parlayacağı yer de burası. ✨
### Birden Fazla Model Oluşturma { #create-multiple-models }
**SQLModel**’de, `table=True` olan herhangi bir model sınıfı bir **table model**’dir.
`table=True` olmayan her model sınıfı ise bir **data model**’dir; bunlar aslında sadece Pydantic modelleridir (bazı küçük ek özelliklerle).
`table=True` olmayan her model sınıfı ise bir **data model**’dir; bunlar aslında sadece Pydantic modelleridir (bazı küçük ek özelliklerle). 🤓
SQLModel ile **inheritance** kullanarak her durumda tüm alanları tekrar tekrar yazmaktan **kaçınabiliriz**.
@ -216,7 +216,7 @@ Sonraki adımda `HeroPublic` modelini oluştururuz; bu model API client’ların
`HeroBase` ile aynı alanlara sahiptir; dolayısıyla `secret_name` içermez.
Sonunda kahramanlarımızın kimliği korunmuş oldu!
Sonunda kahramanlarımızın kimliği korunmuş oldu! 🥷
Ayrıca `id: int` alanını yeniden tanımlar. Bunu yaparak API client’larıyla bir **contract** (sözleşme) oluşturmuş oluruz; böylece `id` alanının her zaman var olacağını ve `int` olacağını (asla `None` olmayacağını) bilirler.
@ -224,7 +224,7 @@ Ayrıca `id: int` alanını yeniden tanımlar. Bunu yaparak API client’larıyl
Return model’in bir değerin her zaman mevcut olduğunu ve her zaman `int` olduğunu (`None` değil) garanti etmesi API client’ları için çok faydalıdır; bu kesinlik sayesinde daha basit kod yazabilirler.
Ayrıca **otomatik üretilen client**’ların arayüzleri de daha basit olur; böylece API’nizle çalışan geliştiriciler için süreç çok daha rahat olur.
Ayrıca **otomatik üretilen client**’ların arayüzleri de daha basit olur; böylece API’nizle çalışan geliştiriciler için süreç çok daha rahat olur. 😎
///
@ -262,13 +262,13 @@ Ayrıca password değerlerini saklamadan önce **hash** etmelisiniz; **asla plai
Uygulamanın önceki sürümünde bir hero’yu **güncellemenin** bir yolu yoktu; ancak artık **birden fazla model** ile bunu yapabiliriz.
Uygulamanın önceki sürümünde bir hero’yu **güncellemenin** bir yolu yoktu; ancak artık **birden fazla model** ile bunu yapabiliriz. 🎉
`HeroUpdate`*data model* biraz özeldir: yeni bir hero oluşturmak için gereken alanların **tamamına** sahiptir, ancak tüm alanlar **opsiyoneldir** (hepsinin bir default değeri vardır). Bu sayede hero güncellerken sadece güncellemek istediğiniz alanları gönderebilirsiniz.
Tüm **alanlar aslında değiştiği** için (tip artık `None` içeriyor ve default değerleri `None` oluyor), onları **yeniden tanımlamamız** gerekir.
Aslında `HeroBase`’ten miras almamız gerekmiyor; çünkü tüm alanları yeniden tanımlıyoruz. Tutarlılık için miras almayı bırakıyorum ama bu gerekli değil. Daha çok kişisel tercih meselesi.
Aslında `HeroBase`’ten miras almamız gerekmiyor; çünkü tüm alanları yeniden tanımlıyoruz. Tutarlılık için miras almayı bırakıyorum ama bu gerekli değil. Daha çok kişisel tercih meselesi. 🤷
`HeroUpdate` alanları:
@ -316,7 +316,7 @@ Tek bir hero’yu **okuyabiliriz**:
Bir hero’yu **güncelleyebiliriz**. Bunun için HTTP `PATCH` operasyonu kullanırız.
Kodda, client’ın gönderdiği tüm verilerle bir `dict` alırız; **yalnızca client’ın gönderdiği veriler**, yani sadece default değer oldukları için orada bulunan değerler hariç. Bunu yapmak için `exclude_unset=True` kullanırız. Asıl numara bu.
Kodda, client’ın gönderdiği tüm verilerle bir `dict` alırız; **yalnızca client’ın gönderdiği veriler**, yani sadece default değer oldukları için orada bulunan değerler hariç. Bunu yapmak için `exclude_unset=True` kullanırız. Asıl numara bu. 🪄
Sonra `hero_db.sqlmodel_update(hero_data)` ile `hero_db`’yi `hero_data` içindeki verilerle güncelleriz.
@ -326,7 +326,7 @@ Sonra `hero_db.sqlmodel_update(hero_data)` ile `hero_db`’yi `hero_data` içind
Bir hero’yu **silmek** büyük ölçüde aynı kalıyor.
Bu örnekte her şeyi refactor etme isteğimizi bastıracağız.
Bu örnekte her şeyi refactor etme isteğimizi bastıracağız. 😅
Bir SQL veritabanıyla etkileşim kurmak için <ahref="https://sqlmodel.tiangolo.com/"class="external-link"target="_blank">**SQLModel**</a> kullanabilir ve *data model* ile *table model* yaklaşımıyla kodu sadeleştirebilirsiniz.
**SQLModel** dokümantasyonunda çok daha fazlasını öğrenebilirsiniz; **FastAPI** ile SQLModel kullanımı için daha uzun bir mini <ahref="https://sqlmodel.tiangolo.com/tutorial/fastapi/"class="external-link"target="_blank">tutorial</a> da bulunuyor.
**SQLModel** dokümantasyonunda çok daha fazlasını öğrenebilirsiniz; **FastAPI** ile SQLModel kullanımı için daha uzun bir mini <ahref="https://sqlmodel.tiangolo.com/tutorial/fastapi/"class="external-link"target="_blank">tutorial</a> da bulunuyor. 🚀
Bu, bir `APIRouter` kullanmaktan farklıdır; çünkü mount edilen uygulama tamamen bağımsızdır. Ana uygulamanızın OpenAPI ve docs'ları, mount edilen uygulamadan hiçbir şey içermez, vb.
Bununla ilgili daha fazla bilgiyi [Advanced User Guide](../advanced/index.md){.internal-link target=_blank} içinde okuyabilirsiniz.
Bununla ilgili daha fazla bilgiyi [Gelişmiş Kullanıcı Kılavuzu](../advanced/index.md){.internal-link target=_blank} içinde okuyabilirsiniz.
@ -12,7 +12,7 @@ Bununla birlikte **FastAPI** ile <a href="https://docs.pytest.org/" class="exter
`TestClient` kullanmak için önce <ahref="https://www.python-httpx.org"class="external-link"target="_blank">`httpx`</a>'i kurun.
Bir [virtual environment](../virtual-environments.md){.internal-link target=_blank} oluşturduğunuzdan, onu aktifleştirdiğinizden ve sonra kurulumu yaptığınızdan emin olun; örneğin:
Bir [Sanal Ortam](../virtual-environments.md){.internal-link target=_blank} oluşturduğunuzdan, onu aktifleştirdiğinizden ve sonra kurulumu yaptığınızdan emin olun; örneğin:
```console
$ pip install httpx
@ -30,7 +30,7 @@ Adı `test_` ile başlayan fonksiyonlar oluşturun (bu, `pytest`'in standart kon
Kontrol etmeniz gereken şeyler için standart Python ifadeleriyle basit `assert` satırları yazın (bu da `pytest` standardıdır).
...ve test kodunu da öncekiyle aynı şekilde yazabilirsiniz.
@ -145,7 +145,7 @@ Backend'e veri geçme hakkında daha fazla bilgi için (`httpx` veya `TestClient
`TestClient`'ın Pydantic model'lerini değil, JSON'a dönüştürülebilen verileri aldığını unutmayın.
Testinizde bir Pydantic model'iniz varsa ve test sırasında verisini uygulamaya göndermek istiyorsanız, [JSON Compatible Encoder](encoder.md){.internal-link target=_blank} içinde açıklanan `jsonable_encoder`'ı kullanabilirsiniz.
Testinizde bir Pydantic model'iniz varsa ve test sırasında verisini uygulamaya göndermek istiyorsanız, [JSON Uyumlu Encoder](encoder.md){.internal-link target=_blank} içinde açıklanan `jsonable_encoder`'ı kullanabilirsiniz.
///
@ -153,7 +153,7 @@ Testinizde bir Pydantic model'iniz varsa ve test sırasında verisini uygulamaya
Bundan sonra yapmanız gereken tek şey `pytest`'i kurmaktır.
Bir [virtual environment](../virtual-environments.md){.internal-link target=_blank} oluşturduğunuzdan, onu aktifleştirdiğinizden ve sonra kurulumu yaptığınızdan emin olun; örneğin:
Bir [Sanal Ortam](../virtual-environments.md){.internal-link target=_blank} oluşturduğunuzdan, onu aktifleştirdiğinizden ve sonra kurulumu yaptığınızdan emin olun; örneğin:
Bir Python projesi üzerinde **ilk kez** çalışmaya başladığınızda, projenizin içinde **<abbrtitle="there are other options, this is a simple guideline">virtual environment</abbr>** oluşturun.
Bir Python projesi üzerinde **ilk kez** çalışmaya başladığınızda, **virtual environment**'i <dfntitle="başka seçenekler de var, bu basit bir yönergedir">projenizin içinde</dfn> oluşturun.