# `yield` ile Dependency'ler { #dependencies-with-yield } FastAPI, işini bitirdikten sonra ek adımlar ç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. /// /// note | Teknik Detaylar Şunlarla kullanılabilen herhangi bir fonksiyon: * `@contextlib.contextmanager` veya * `@contextlib.asynccontextmanager` bir **FastAPI** dependency'si olarak kullanılabilir. Hatta FastAPI bu iki decorator'ı içeride (internally) kullanır. /// ## `yield` ile Bir Veritabanı Dependency'si { #a-database-dependency-with-yield } Örneğin bunu, bir veritabanı session'ı oluşturmak ve iş bittikten sonra kapatmak için kullanabilirsiniz. Response oluşturulmadan önce yalnızca `yield` satırına kadar olan (ve `yield` dahil) kod çalıştırılır: {* ../../docs_src/dependencies/tutorial007_py310.py hl[2:4] *} `yield` edilen değer, *path operation*'lara ve diğer dependency'lere enjekte edilen (injected) değerdir: {* ../../docs_src/dependencies/tutorial007_py310.py hl[4] *} Response'dan sonra `yield` satırını takip eden kod çalıştırılır: {* ../../docs_src/dependencies/tutorial007_py310.py hl[5:6] *} /// tip | İpucu `async` ya da normal fonksiyonlar kullanabilirsiniz. **FastAPI**, normal dependency'lerde olduğu gibi her ikisinde de doğru şekilde davranır. /// ## `yield` ve `try` ile Bir Dependency { #a-dependency-with-yield-and-try } `yield` kullanan bir dependency içinde bir `try` bloğu kullanırsanız, dependency kullanılırken fırlatılan (raised) herhangi bir exception'ı alırsınız. Örneğin, başka bir dependency'de veya bir *path operation* içinde çalışan bir kod, bir veritabanı transaction'ını "rollback" yaptıysa ya da başka bir exception oluşturduysa, o exception dependency'nizde size gelir. Dolayısıyla `except SomeException` ile dependency içinde o spesifik exception'ı yakalayabilirsiniz. Aynı şekilde, exception olsun ya da olmasın çıkış (exit) adımlarının çalıştırılmasını garanti etmek için `finally` kullanabilirsiniz. {* ../../docs_src/dependencies/tutorial007_py310.py hl[3,5] *} ## `yield` ile Alt Dependency'ler { #sub-dependencies-with-yield } Her boyutta ve şekilde alt dependency'ler ve alt dependency "ağaçları" (trees) oluşturabilirsiniz; bunların herhangi biri veya hepsi `yield` kullanabilir. **FastAPI**, `yield` kullanan her dependency'deki "exit code"'un doğru sırayla çalıştırılmasını sağlar. Örneğin, `dependency_c`, `dependency_b`'ye; `dependency_b` de `dependency_a`'ya bağlı olabilir: {* ../../docs_src/dependencies/tutorial008_an_py310.py hl[6,14,22] *} Ve hepsi `yield` kullanabilir. Bu durumda `dependency_c`, exit code'unu çalıştırabilmek için `dependency_b`'den gelen değerin (burada `dep_b`) hâlâ erişilebilir olmasına ihtiyaç duyar. Aynı şekilde `dependency_b` de exit code'u için `dependency_a`'dan gelen değerin (burada `dep_a`) erişilebilir olmasına ihtiyaç duyar. {* ../../docs_src/dependencies/tutorial008_an_py310.py hl[18:19,26:27] *} Benzer şekilde, bazı dependency'ler `yield`, bazıları `return` kullanabilir ve bunların bazıları diğerlerine bağlı olabilir. Ayrıca birden fazla `yield` kullanan dependency gerektiren tek bir dependency'niz de olabilir, vb. İstediğiniz herhangi bir dependency kombinasyonunu kullanabilirsiniz. **FastAPI** her şeyin doğru sırada çalışmasını sağlar. /// note | Teknik Detaylar Bu, Python'un Context Managers yapısı sayesinde çalışır. **FastAPI** bunu sağlamak için içeride onları kullanır. /// ## `yield` ve `HTTPException` ile Dependency'ler { #dependencies-with-yield-and-httpexception } `yield` kullanan dependency'lerde `try` bloklarıyla bazı kodları çalıştırıp ardından `finally` sonrasında exit code çalıştırabileceğinizi gördünüz. Ayrıca `except` ile fırlatılan exception'ı yakalayıp onunla bir şey yapabilirsiniz. Örneğin `HTTPException` gibi farklı bir exception fırlatabilirsiniz. /// tip | İpucu Bu biraz ileri seviye bir tekniktir ve çoğu durumda gerçekten ihtiyaç duymazsınız; çünkü exception'ları (`HTTPException` dahil) uygulamanızın geri kalan kodundan, örneğin *path operation function* içinden fırlatabilirsiniz. Ama ihtiyaç duyarsanız diye burada. 🤓 /// {* ../../docs_src/dependencies/tutorial008b_an_py310.py hl[18:22,31] *} 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. ## `yield` ve `except` ile Dependency'ler { #dependencies-with-yield-and-except } `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: {* ../../docs_src/dependencies/tutorial008c_an_py310.py hl[15:16] *} 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. 😱 ### `yield` ve `except` Kullanan Dependency'lerde Her Zaman `raise` Edin { #always-raise-in-dependencies-with-yield-and-except } `yield` kullanan bir dependency içinde bir exception yakalarsanız, başka bir `HTTPException` veya benzeri bir şey fırlatmıyorsanız, **orijinal exception'ı tekrar raise etmelisiniz**. Aynı exception'ı `raise` ile tekrar fırlatabilirsiniz: {* ../../docs_src/dependencies/tutorial008d_an_py310.py hl[17] *} Artık client yine aynı *HTTP 500 Internal Server Error* response'unu alır, ama server log'larda bizim özel `InternalError`'ımızı görür. 😎 ## `yield` Kullanan Dependency'lerin Çalıştırılması { #execution-of-dependencies-with-yield } Çalıştırma sırası kabaca aşağıdaki diyagramdaki gibidir. Zaman yukarıdan aşağı akar. Her sütun, etkileşime giren veya kod çalıştıran parçalardan birini temsil eder. ```mermaid sequenceDiagram participant client as Client participant handler as Exception handler participant dep as Dep with yield participant operation as Path Operation participant tasks as Background tasks Note over client,operation: Can raise exceptions, including HTTPException client ->> dep: Start request Note over dep: Run code up to yield opt raise Exception dep -->> handler: Raise Exception handler -->> client: HTTP error response end dep ->> operation: Run dependency, e.g. DB session opt raise operation -->> dep: Raise Exception (e.g. HTTPException) opt handle dep -->> dep: Can catch exception, raise a new HTTPException, raise other exception end handler -->> client: HTTP error response end operation ->> client: Return response to client Note over client,operation: Response is already sent, can't change it anymore opt Tasks operation -->> tasks: Send background tasks end opt Raise other exception tasks -->> tasks: Handle exceptions in the background task code end ``` /// info | Bilgi Client'a yalnızca **tek bir response** gönderilir. Bu, error response'lardan biri olabilir ya da *path operation*'dan dönen response olabilir. Bu response'lardan biri gönderildikten sonra başka bir response gönderilemez. /// /// tip | İpucu *Path operation function* içindeki koddan herhangi bir exception raise ederseniz, `HTTPException` dahil olmak üzere bu exception `yield` kullanan dependency'lere aktarılır. Çoğu durumda, doğru şekilde ele alındığından emin olmak için `yield` kullanan dependency'den aynı exception'ı (veya yeni bir tanesini) yeniden raise etmek istersiniz. /// ## Erken Çıkış ve `scope` { #early-exit-and-scope } Normalde `yield` kullanan dependency'lerin exit code'u, client'a response gönderildikten **sonra** çalıştırılır. 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. {* ../../docs_src/dependencies/tutorial008e_an_py310.py hl[12,16] *} `Depends()` şu değerleri alabilen bir `scope` parametresi alır: * `"function"`: dependency'yi request'i işleyen *path operation function* çalışmadan önce başlat, *path operation function* bittikten sonra bitir, ancak response client'a geri gönderilmeden **önce** sonlandır. Yani dependency fonksiyonu, *path operation **function***'ın **etrafında** çalıştırılır. * `"request"`: dependency'yi request'i işleyen *path operation function* çalışmadan önce başlat (`"function"` kullanımına benzer), ancak response client'a geri gönderildikten **sonra** sonlandır. Yani dependency fonksiyonu, **request** ve response döngüsünün **etrafında** çalıştırılır. Belirtilmezse ve dependency `yield` kullanıyorsa, varsayılan olarak `scope` `"request"` olur. ### Alt dependency'ler için `scope` { #scope-for-sub-dependencies } `scope="request"` (varsayılan) ile bir dependency tanımladığınızda, herhangi bir alt dependency'nin `scope` değeri de `"request"` olmalıdır. Ancak `scope` değeri `"function"` olan bir dependency, hem `"function"` hem de `"request"` scope'una sahip dependency'lere bağlı olabilir. Bunun nedeni, bir dependency'nin exit code'unu alt dependency'lerden önce çalıştırabilmesi gerekmesidir; çünkü exit code sırasında hâlâ onları kullanması gerekebilir. ```mermaid sequenceDiagram participant client as Client participant dep_req as Dep scope="request" participant dep_func as Dep scope="function" participant operation as Path Operation client ->> dep_req: Start request Note over dep_req: Run code up to yield dep_req ->> dep_func: Pass dependency Note over dep_func: Run code up to yield dep_func ->> operation: Run path operation with dependency operation ->> dep_func: Return from path operation Note over dep_func: Run code after yield Note over dep_func: ✅ Dependency closed dep_func ->> client: Send response to client Note over client: Response sent Note over dep_req: Run code after yield Note over dep_req: ✅ Dependency closed ``` ## `yield`, `HTTPException`, `except` ve Background Tasks ile Dependency'ler { #dependencies-with-yield-httpexception-except-and-background-tasks } `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}. ## Context Managers { #context-managers } ### "Context Managers" Nedir? { #what-are-context-managers } "Context Managers", `with` ifadesiyle kullanabildiğiniz Python nesneleridir. Örneğin, bir dosyayı okumak için `with` kullanabilirsiniz: ```Python with open("./somefile.txt") as f: contents = f.read() print(contents) ``` Temelde `open("./somefile.txt")`, "Context Manager" olarak adlandırılan bir nesne oluşturur. `with` bloğu bittiğinde, exception olsa bile dosyanın kapatılmasını garanti eder. `yield` ile bir dependency oluşturduğunuzda, **FastAPI** içeride bunun için bir context manager oluşturur ve bazı ilgili başka araçlarla birleştirir. ### `yield` kullanan dependency'lerde context manager kullanma { #using-context-managers-in-dependencies-with-yield } /// warning | Uyarı Bu, az çok "ileri seviye" bir fikirdir. **FastAPI**'ye yeni başlıyorsanız şimdilik bunu atlamak isteyebilirsiniz. /// Python'da Context Manager'ları, iki method'a sahip bir class oluşturarak: `__enter__()` ve `__exit__()` yaratabilirsiniz. Ayrıca dependency fonksiyonunun içinde `with` veya `async with` ifadeleri kullanarak **FastAPI**'de `yield` kullanan dependency'lerin içinde de kullanabilirsiniz: {* ../../docs_src/dependencies/tutorial010_py310.py hl[1:9,13] *} /// tip | İpucu Bir context manager oluşturmanın başka bir yolu da şunlardır: * `@contextlib.contextmanager` veya * `@contextlib.asynccontextmanager` Bunları, tek bir `yield` içeren bir fonksiyonu decorate etmek için kullanabilirsiniz. FastAPI, `yield` kullanan dependency'ler için içeride bunu yapar. Ancak FastAPI dependency'leri için bu decorator'ları kullanmak zorunda değilsiniz (hatta kullanmamalısınız). FastAPI bunu sizin yerinize içeride yapar. ///