Browse Source

Merge branch 'master' of https://github.com/harol97/fastapi into fix/conider-alias-in-form

pull/10319/head
Harol Alvarado 1 year ago
parent
commit
0c8b8a1d1e
  1. 2
      README.md
  2. 5
      docs/az/learn/index.md
  3. 36
      docs/de/docs/external-links.md
  4. 5
      docs/de/docs/newsletter.md
  5. 11
      docs/de/docs/reference/background.md
  6. 3
      docs/de/docs/reference/encoders.md
  7. 31
      docs/de/docs/reference/fastapi.md
  8. 14
      docs/de/docs/reference/request.md
  9. 164
      docs/de/docs/reference/responses.md
  10. 13
      docs/de/docs/reference/templating.md
  11. 12
      docs/en/data/sponsors.yml
  12. 49
      docs/en/docs/release-notes.md
  13. 70
      docs/en/docs/tutorial/dependencies/dependencies-with-yield.md
  14. 227
      docs/tr/docs/tutorial/query-params.md
  15. 27
      docs_src/dependencies/tutorial008c.py
  16. 28
      docs_src/dependencies/tutorial008c_an.py
  17. 29
      docs_src/dependencies/tutorial008c_an_py39.py
  18. 28
      docs_src/dependencies/tutorial008d.py
  19. 29
      docs_src/dependencies/tutorial008d_an.py
  20. 30
      docs_src/dependencies/tutorial008d_an_py39.py
  21. 2
      fastapi/__init__.py
  22. 108
      fastapi/routing.py
  23. 2
      tests/test_dependency_contextmanager.py
  24. 1
      tests/test_dependency_normal_exceptions.py
  25. 20
      tests/test_tutorial/test_dependencies/test_tutorial008b_an_py39.py
  26. 38
      tests/test_tutorial/test_dependencies/test_tutorial008c.py
  27. 38
      tests/test_tutorial/test_dependencies/test_tutorial008c_an.py
  28. 44
      tests/test_tutorial/test_dependencies/test_tutorial008c_an_py39.py
  29. 41
      tests/test_tutorial/test_dependencies/test_tutorial008d.py
  30. 41
      tests/test_tutorial/test_dependencies/test_tutorial008d_an.py
  31. 47
      tests/test_tutorial/test_dependencies/test_tutorial008d_an_py39.py

2
README.md

@ -55,9 +55,7 @@ The key features are:
<a href="https://www.propelauth.com/?utm_source=fastapi&utm_campaign=1223&utm_medium=mainbadge" target="_blank" title="Auth, user management and more for your B2B product"><img src="https://fastapi.tiangolo.com/img/sponsors/propelauth.png"></a>
<a href="https://www.withcoherence.com/?utm_medium=advertising&utm_source=fastapi&utm_campaign=banner%20january%2024" target="_blank" title="Coherence"><img src="https://fastapi.tiangolo.com/img/sponsors/coherence.png"></a>
<a href="https://training.talkpython.fm/fastapi-courses" target="_blank" title="FastAPI video courses on demand from people you trust"><img src="https://fastapi.tiangolo.com/img/sponsors/talkpython-v2.jpg"></a>
<a href="https://testdriven.io/courses/tdd-fastapi/" target="_blank" title="Learn to build high-quality web apps with best practices"><img src="https://fastapi.tiangolo.com/img/sponsors/testdriven.svg"></a>
<a href="https://github.com/deepset-ai/haystack/" target="_blank" title="Build powerful search from composable, open source building blocks"><img src="https://fastapi.tiangolo.com/img/sponsors/haystack-fastapi.svg"></a>
<a href="https://careers.powens.com/" target="_blank" title="Powens is hiring!"><img src="https://fastapi.tiangolo.com/img/sponsors/powens.png"></a>
<a href="https://databento.com/" target="_blank" title="Pay as you go for market data"><img src="https://fastapi.tiangolo.com/img/sponsors/databento.svg"></a>
<a href="https://speakeasyapi.dev?utm_source=fastapi+repo&utm_medium=github+sponsorship" target="_blank" title="SDKs for your API | Speakeasy"><img src="https://fastapi.tiangolo.com/img/sponsors/speakeasy.png"></a>
<a href="https://www.svix.com/" target="_blank" title="Svix - Webhooks as a service"><img src="https://fastapi.tiangolo.com/img/sponsors/svix.svg"></a>

5
docs/az/learn/index.md

@ -0,0 +1,5 @@
# Öyrən
Burada **FastAPI** öyrənmək üçün giriş bölmələri və dərsliklər yer alır.
Siz bunu kitab, kurs, FastAPI öyrənmək üçün rəsmi və tövsiyə olunan üsul hesab edə bilərsiniz. 😎

36
docs/de/docs/external-links.md

@ -0,0 +1,36 @@
# Externe Links und Artikel
**FastAPI** hat eine großartige Community, die ständig wächst.
Es gibt viele Beiträge, Artikel, Tools und Projekte zum Thema **FastAPI**.
Hier ist eine unvollständige Liste einiger davon.
!!! tip "Tipp"
Wenn Sie einen Artikel, ein Projekt, ein Tool oder irgendetwas im Zusammenhang mit **FastAPI** haben, was hier noch nicht aufgeführt ist, erstellen Sie einen <a href="https://github.com/tiangolo/fastapi/edit/master/docs/en/data/external_links.yml" class="external-link" target="_blank">Pull Request und fügen Sie es hinzu</a>.
!!! note "Hinweis Deutsche Übersetzung"
Die folgenden Überschriften und Links werden aus einer <a href="https://github.com/tiangolo/fastapi/blob/master/docs/en/data/external_links.yml" class="external-link" target="_blank">anderen Datei</a> gelesen und sind daher nicht ins Deutsche übersetzt.
{% for section_name, section_content in external_links.items() %}
## {{ section_name }}
{% for lang_name, lang_content in section_content.items() %}
### {{ lang_name }}
{% for item in lang_content %}
* <a href="{{ item.link }}" class="external-link" target="_blank">{{ item.title }}</a> by <a href="{{ item.author_link }}" class="external-link" target="_blank">{{ item.author }}</a>.
{% endfor %}
{% endfor %}
{% endfor %}
## Projekte
Die neuesten GitHub-Projekte zum Thema `fastapi`:
<div class="github-topic-projects">
</div>

5
docs/de/docs/newsletter.md

@ -0,0 +1,5 @@
# FastAPI und Freunde Newsletter
<iframe data-w-type="embedded" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="https://xr4n4.mjt.lu/wgt/xr4n4/hj5/form?c=40a44fa4" width="100%" style="height: 0;"></iframe>
<script type="text/javascript" src="https://app.mailjet.com/pas-nc-embedded-v1.js"></script>

11
docs/de/docs/reference/background.md

@ -0,0 +1,11 @@
# Hintergrundtasks – `BackgroundTasks`
Sie können einen Parameter in einer *Pfadoperation-Funktion* oder einer Abhängigkeitsfunktion mit dem Typ `BackgroundTasks` deklarieren und diesen danach verwenden, um die Ausführung von Hintergrundtasks nach dem Senden der Response zu definieren.
Sie können `BackgroundTasks` direkt von `fastapi` importieren:
```python
from fastapi import BackgroundTasks
```
::: fastapi.BackgroundTasks

3
docs/de/docs/reference/encoders.md

@ -0,0 +1,3 @@
# Encoder – `jsonable_encoder`
::: fastapi.encoders.jsonable_encoder

31
docs/de/docs/reference/fastapi.md

@ -0,0 +1,31 @@
# `FastAPI`-Klasse
Hier sind die Referenzinformationen für die Klasse `FastAPI` mit all ihren Parametern, Attributen und Methoden.
Sie können die `FastAPI`-Klasse direkt von `fastapi` importieren:
```python
from fastapi import FastAPI
```
::: fastapi.FastAPI
options:
members:
- openapi_version
- webhooks
- state
- dependency_overrides
- openapi
- websocket
- include_router
- get
- put
- post
- delete
- options
- head
- patch
- trace
- on_event
- middleware
- exception_handler

14
docs/de/docs/reference/request.md

@ -0,0 +1,14 @@
# `Request`-Klasse
Sie können einen Parameter in einer *Pfadoperation-Funktion* oder einer Abhängigkeit als vom Typ `Request` deklarieren und dann direkt auf das Requestobjekt zugreifen, ohne jegliche Validierung, usw.
Sie können es direkt von `fastapi` importieren:
```python
from fastapi import Request
```
!!! tip "Tipp"
Wenn Sie Abhängigkeiten definieren möchten, die sowohl mit HTTP als auch mit WebSockets kompatibel sein sollen, können Sie einen Parameter definieren, der eine `HTTPConnection` anstelle eines `Request` oder eines `WebSocket` akzeptiert.
::: fastapi.Request

164
docs/de/docs/reference/responses.md

@ -0,0 +1,164 @@
# Benutzerdefinierte Responseklassen – File, HTML, Redirect, Streaming, usw.
Es gibt mehrere benutzerdefinierte Responseklassen, von denen Sie eine Instanz erstellen und diese direkt von Ihren *Pfadoperationen* zurückgeben können.
Lesen Sie mehr darüber in der [FastAPI-Dokumentation zu benutzerdefinierten Responses – HTML, Stream, Datei, andere](../advanced/custom-response.md).
Sie können diese direkt von `fastapi.responses` importieren:
```python
from fastapi.responses import (
FileResponse,
HTMLResponse,
JSONResponse,
ORJSONResponse,
PlainTextResponse,
RedirectResponse,
Response,
StreamingResponse,
UJSONResponse,
)
```
## FastAPI-Responses
Es gibt einige benutzerdefinierte FastAPI-Responseklassen, welche Sie verwenden können, um die JSON-Performanz zu optimieren.
::: fastapi.responses.UJSONResponse
options:
members:
- charset
- status_code
- media_type
- body
- background
- raw_headers
- render
- init_headers
- headers
- set_cookie
- delete_cookie
::: fastapi.responses.ORJSONResponse
options:
members:
- charset
- status_code
- media_type
- body
- background
- raw_headers
- render
- init_headers
- headers
- set_cookie
- delete_cookie
## Starlette-Responses
::: fastapi.responses.FileResponse
options:
members:
- chunk_size
- charset
- status_code
- media_type
- body
- background
- raw_headers
- render
- init_headers
- headers
- set_cookie
- delete_cookie
::: fastapi.responses.HTMLResponse
options:
members:
- charset
- status_code
- media_type
- body
- background
- raw_headers
- render
- init_headers
- headers
- set_cookie
- delete_cookie
::: fastapi.responses.JSONResponse
options:
members:
- charset
- status_code
- media_type
- body
- background
- raw_headers
- render
- init_headers
- headers
- set_cookie
- delete_cookie
::: fastapi.responses.PlainTextResponse
options:
members:
- charset
- status_code
- media_type
- body
- background
- raw_headers
- render
- init_headers
- headers
- set_cookie
- delete_cookie
::: fastapi.responses.RedirectResponse
options:
members:
- charset
- status_code
- media_type
- body
- background
- raw_headers
- render
- init_headers
- headers
- set_cookie
- delete_cookie
::: fastapi.responses.Response
options:
members:
- charset
- status_code
- media_type
- body
- background
- raw_headers
- render
- init_headers
- headers
- set_cookie
- delete_cookie
::: fastapi.responses.StreamingResponse
options:
members:
- body_iterator
- charset
- status_code
- media_type
- body
- background
- raw_headers
- render
- init_headers
- headers
- set_cookie
- delete_cookie

13
docs/de/docs/reference/templating.md

@ -0,0 +1,13 @@
# Templating – `Jinja2Templates`
Sie können die `Jinja2Templates`-Klasse verwenden, um Jinja-Templates zu rendern.
Lesen Sie mehr darüber in der [FastAPI-Dokumentation zu Templates](../advanced/templates.md).
Sie können die Klasse direkt von `fastapi.templating` importieren:
```python
from fastapi.templating import Jinja2Templates
```
::: fastapi.templating.Jinja2Templates

12
docs/en/data/sponsors.yml

@ -27,15 +27,9 @@ silver:
- url: https://training.talkpython.fm/fastapi-courses
title: FastAPI video courses on demand from people you trust
img: https://fastapi.tiangolo.com/img/sponsors/talkpython-v2.jpg
- url: https://testdriven.io/courses/tdd-fastapi/
title: Learn to build high-quality web apps with best practices
img: https://fastapi.tiangolo.com/img/sponsors/testdriven.svg
- url: https://github.com/deepset-ai/haystack/
title: Build powerful search from composable, open source building blocks
img: https://fastapi.tiangolo.com/img/sponsors/haystack-fastapi.svg
- url: https://careers.powens.com/
title: Powens is hiring!
img: https://fastapi.tiangolo.com/img/sponsors/powens.png
- url: https://databento.com/
title: Pay as you go for market data
img: https://fastapi.tiangolo.com/img/sponsors/databento.svg
@ -52,6 +46,6 @@ bronze:
- url: https://www.exoflare.com/open-source/?utm_source=FastAPI&utm_campaign=open_source
title: Biosecurity risk assessments made easy.
img: https://fastapi.tiangolo.com/img/sponsors/exoflare.png
- url: https://bit.ly/3JJ7y5C
title: Build cross-modal and multimodal applications on the cloud
img: https://fastapi.tiangolo.com/img/sponsors/jina2.svg
- url: https://testdriven.io/courses/tdd-fastapi/
title: Learn to build high-quality web apps with best practices
img: https://fastapi.tiangolo.com/img/sponsors/testdriven.svg

49
docs/en/docs/release-notes.md

@ -7,6 +7,43 @@ hide:
## Latest Changes
### Translations
* 🌐 Add Azerbaijani translation for `docs/az/learn/index.md`. PR [#11192](https://github.com/tiangolo/fastapi/pull/11192) by [@vusallyv](https://github.com/vusallyv).
### Internal
* 🔧 Update sponsors, remove Jina, remove Powens, move TestDriven.io. PR [#11213](https://github.com/tiangolo/fastapi/pull/11213) by [@tiangolo](https://github.com/tiangolo).
## 0.110.0
### Breaking Changes
* 🐛 Fix unhandled growing memory for internal server errors, refactor dependencies with `yield` and `except` to require raising again as in regular Python. PR [#11191](https://github.com/tiangolo/fastapi/pull/11191) by [@tiangolo](https://github.com/tiangolo).
* This is a breaking change (and only slightly) if you used dependencies with `yield`, used `except` in those dependencies, and didn't raise again.
* This was reported internally by [@rushilsrivastava](https://github.com/rushilsrivastava) as a memory leak when the server had unhandled exceptions that would produce internal server errors, the memory allocated before that point would not be released.
* Read the new docs: [Dependencies with `yield` and `except`](https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/#dependencies-with-yield-and-except).
In short, if you had dependencies that looked like:
```Python
def my_dep():
try:
yield
except SomeException:
pass
```
Now you need to make sure you raise again after `except`, just as you would in regular Python:
```Python
def my_dep():
try:
yield
except SomeException:
raise
```
### Docs
* ✏️ Fix minor typos in `docs/ko/docs/`. PR [#11126](https://github.com/tiangolo/fastapi/pull/11126) by [@KaniKim](https://github.com/KaniKim).
@ -14,6 +51,16 @@ hide:
### Translations
* 🌐 Add German translation for `docs/de/docs/reference/background.md`. PR [#10820](https://github.com/tiangolo/fastapi/pull/10820) by [@nilslindemann](https://github.com/nilslindemann).
* 🌐 Add German translation for `docs/de/docs/reference/templating.md`. PR [#10842](https://github.com/tiangolo/fastapi/pull/10842) by [@nilslindemann](https://github.com/nilslindemann).
* 🌐 Add German translation for `docs/de/docs/external-links.md`. PR [#10852](https://github.com/tiangolo/fastapi/pull/10852) by [@nilslindemann](https://github.com/nilslindemann).
* 🌐 Update Turkish translation for `docs/tr/docs/tutorial/query-params.md`. PR [#11162](https://github.com/tiangolo/fastapi/pull/11162) by [@hasansezertasan](https://github.com/hasansezertasan).
* 🌐 Add German translation for `docs/de/docs/reference/encoders.md`. PR [#10840](https://github.com/tiangolo/fastapi/pull/10840) by [@nilslindemann](https://github.com/nilslindemann).
* 🌐 Add German translation for `docs/de/docs/reference/responses.md`. PR [#10825](https://github.com/tiangolo/fastapi/pull/10825) by [@nilslindemann](https://github.com/nilslindemann).
* 🌐 Add German translation for `docs/de/docs/reference/request.md`. PR [#10821](https://github.com/tiangolo/fastapi/pull/10821) by [@nilslindemann](https://github.com/nilslindemann).
* 🌐 Add Turkish translation for `docs/tr/docs/tutorial/query-params.md`. PR [#11078](https://github.com/tiangolo/fastapi/pull/11078) by [@emrhnsyts](https://github.com/emrhnsyts).
* 🌐 Add German translation for `docs/de/docs/reference/fastapi.md`. PR [#10813](https://github.com/tiangolo/fastapi/pull/10813) by [@nilslindemann](https://github.com/nilslindemann).
* 🌐 Add German translation for `docs/de/docs/newsletter.md`. PR [#10853](https://github.com/tiangolo/fastapi/pull/10853) by [@nilslindemann](https://github.com/nilslindemann).
* 🌐 Add Traditional Chinese translation for `docs/zh-hant/docs/learn/index.md`. PR [#11142](https://github.com/tiangolo/fastapi/pull/11142) by [@hsuanchi](https://github.com/hsuanchi).
* 🌐 Add Korean translation for `/docs/ko/docs/tutorial/dependencies/global-dependencies.md`. PR [#11123](https://github.com/tiangolo/fastapi/pull/11123) by [@riroan](https://github.com/riroan).
* 🌐 Add Korean translation for `/docs/ko/docs/tutorial/dependencies/dependencies-in-path-operation-decorators.md`. PR [#11124](https://github.com/tiangolo/fastapi/pull/11124) by [@riroan](https://github.com/riroan).
@ -281,7 +328,7 @@ Read more in the [advisory: Content-Type Header ReDoS](https://github.com/tiango
### Upgrades
* ⬆️ Upgrade Starlette to `>=0.29.0,<0.33.0`, update docs and usage of templates with new Starlette arguments. PR [#10846](https://github.com/tiangolo/fastapi/pull/10846) by [@tiangolo](https://github.com/tiangolo).
* ⬆️ Upgrade Starlette to `>=0.29.0,<0.33.0`, update docs and usage of templates with new Starlette arguments. Remove pin of AnyIO `>=3.7.1,<4.0.0`, add support for AnyIO 4.x.x. PR [#10846](https://github.com/tiangolo/fastapi/pull/10846) by [@tiangolo](https://github.com/tiangolo).
## 0.107.0

70
docs/en/docs/tutorial/dependencies/dependencies-with-yield.md

@ -162,6 +162,63 @@ The same way, you could raise an `HTTPException` or similar in the exit code, af
An alternative you could use to catch exceptions (and possibly also raise another `HTTPException`) is to create a [Custom Exception Handler](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}.
## Dependencies with `yield` and `except`
If you catch an exception using `except` in a dependency with `yield` and you don't raise it again (or raise a new exception), FastAPI won't be able to notice there was an exception, the same way that would happen with regular Python:
=== "Python 3.9+"
```Python hl_lines="15-16"
{!> ../../../docs_src/dependencies/tutorial008c_an_py39.py!}
```
=== "Python 3.8+"
```Python hl_lines="14-15"
{!> ../../../docs_src/dependencies/tutorial008c_an.py!}
```
=== "Python 3.8+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="13-14"
{!> ../../../docs_src/dependencies/tutorial008c.py!}
```
In this case, the client will see an *HTTP 500 Internal Server Error* response as it should, given that we are not raising an `HTTPException` or similar, but the server will **not have any logs** or any other indication of what was the error. 😱
### Always `raise` in Dependencies with `yield` and `except`
If you catch an exception in a dependency with `yield`, unless you are raising another `HTTPException` or similar, you should re-raise the original exception.
You can re-raise the same exception using `raise`:
=== "Python 3.9+"
```Python hl_lines="17"
{!> ../../../docs_src/dependencies/tutorial008d_an_py39.py!}
```
=== "Python 3.8+"
```Python hl_lines="16"
{!> ../../../docs_src/dependencies/tutorial008d_an.py!}
```
=== "Python 3.8+ non-Annotated"
!!! tip
Prefer to use the `Annotated` version if possible.
```Python hl_lines="15"
{!> ../../../docs_src/dependencies/tutorial008d.py!}
```
Now the client will get the same *HTTP 500 Internal Server Error* response, but the server will have our custom `InternalError` in the logs. 😎
## Execution of dependencies with `yield`
The sequence of execution is more or less like this diagram. Time flows from top to bottom. And each column is one of the parts interacting or executing code.
@ -187,7 +244,6 @@ participant tasks as Background tasks
operation -->> dep: Raise Exception (e.g. HTTPException)
opt handle
dep -->> dep: Can catch exception, raise a new HTTPException, raise other exception
dep -->> handler: Auto forward exception
end
handler -->> client: HTTP error response
end
@ -210,15 +266,23 @@ participant tasks as Background tasks
!!! tip
This diagram shows `HTTPException`, but you could also raise any other exception that you catch in a dependency with `yield` or with a [Custom Exception Handler](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank}.
If you raise any exception, it will be passed to the dependencies with yield, including `HTTPException`, and then **again** to the exception handlers. If there's no exception handler for that exception, it will then be handled by the default internal `ServerErrorMiddleware`, returning a 500 HTTP status code, to let the client know that there was an error in the server.
If you raise any exception, it will be passed to the dependencies with yield, including `HTTPException`. In most cases you will want to re-raise that same exception or a new one from the dependency with `yield` to make sure it's properly handled.
## Dependencies with `yield`, `HTTPException` and Background Tasks
## Dependencies with `yield`, `HTTPException`, `except` and Background Tasks
!!! warning
You most probably don't need these technical details, you can skip this section and continue below.
These details are useful mainly if you were using a version of FastAPI prior to 0.106.0 and used resources from dependencies with `yield` in background tasks.
### Dependencies with `yield` and `except`, Technical Details
Before FastAPI 0.110.0, if you used a dependency with `yield`, and then you captured an exception with `except` in that dependency, and you didn't raise the exception again, the exception would be automatically raised/forwarded to any exception handlers or the internal server error handler.
This was changed in version 0.110.0 to fix unhandled memory consumption from forwarded exceptions without a handler (internal server errors), and to make it consistent with the behavior of regular Python code.
### Background Tasks and Dependencies with `yield`, Technical Details
Before FastAPI 0.106.0, raising exceptions after `yield` was not possible, the exit code in dependencies with `yield` was executed *after* the response was sent, so [Exception Handlers](../handling-errors.md#install-custom-exception-handlers){.internal-link target=_blank} would have already run.
This was designed this way mainly to allow using the same objects "yielded" by dependencies inside of background tasks, because the exit code would be executed after the background tasks were finished.

227
docs/tr/docs/tutorial/query-params.md

@ -0,0 +1,227 @@
# Sorgu Parametreleri
Fonksiyonda yol parametrelerinin parçası olmayan diğer tanımlamalar otomatik olarak "sorgu" parametresi olarak yorumlanır.
```Python hl_lines="9"
{!../../../docs_src/query_params/tutorial001.py!}
```
Sorgu, bağlantıdaki `?` kısmından sonra gelen ve `&` işareti ile ayrılan anahtar-değer çiftlerinin oluşturduğu bir kümedir.
Örneğin, aşağıdaki bağlantıda:
```
http://127.0.0.1:8000/items/?skip=0&limit=10
```
...sorgu parametreleri şunlardır:
* `skip`: değeri `0`'dır
* `limit`: değeri `10`'dır
Parametreler bağlantının bir parçası oldukları için doğal olarak string olarak değerlendirilirler.
Fakat, Python tipleri ile tanımlandıkları zaman (yukarıdaki örnekte `int` oldukları gibi), parametreler o tiplere dönüştürülür ve o tipler çerçevesinde doğrulanırlar.
Yol parametreleri için geçerli olan her türlü işlem aynı şekilde sorgu parametreleri için de geçerlidir:
* Editör desteği (şüphesiz)
* Veri "<abbr title="HTTP isteği ile birlikte gelen string'i Python verisine dönüştürme">ayrıştırma</abbr>"
* Veri doğrulama
* Otomatik dokümantasyon
## Varsayılanlar
Sorgu parametreleri, adres yolunun sabit bir parçası olmadıklarından dolayı isteğe bağlı ve varsayılan değere sahip olabilirler.
Yukarıdaki örnekte `skip=0` ve `limit=10` varsayılan değere sahiplerdir.
Yani, aşağıdaki bağlantıya gitmek:
```
http://127.0.0.1:8000/items/
```
şu adrese gitmek ile aynı etkiye sahiptir:
```
http://127.0.0.1:8000/items/?skip=0&limit=10
```
Ancak, mesela şöyle bir adresi ziyaret ederseniz:
```
http://127.0.0.1:8000/items/?skip=20
```
Fonksiyonunuzdaki parametre değerleri aşağıdaki gibi olacaktır:
* `skip=20`: çünkü bağlantıda böyle tanımlandı.
* `limit=10`: çünkü varsayılan değer buydu.
## İsteğe Bağlı Parametreler
Aynı şekilde, varsayılan değerlerini `None` olarak atayarak isteğe bağlı parametreler tanımlayabilirsiniz:
=== "Python 3.10+"
```Python hl_lines="7"
{!> ../../../docs_src/query_params/tutorial002_py310.py!}
```
=== "Python 3.8+"
```Python hl_lines="9"
{!> ../../../docs_src/query_params/tutorial002.py!}
```
Bu durumda, `q` fonksiyon parametresi isteğe bağlı olacak ve varsayılan değer olarak `None` alacaktır.
!!! check "Ek bilgi"
Ayrıca, dikkatinizi çekerim ki; **FastAPI**, `item_id` parametresinin bir yol parametresi olduğunu ve `q` parametresinin yol değil bir sorgu parametresi olduğunu fark edecek kadar beceriklidir.
## Sorgu Parametresi Tip Dönüşümü
Aşağıda görüldüğü gibi dönüştürülmek üzere `bool` tipleri de tanımlayabilirsiniz:
=== "Python 3.10+"
```Python hl_lines="7"
{!> ../../../docs_src/query_params/tutorial003_py310.py!}
```
=== "Python 3.8+"
```Python hl_lines="9"
{!> ../../../docs_src/query_params/tutorial003.py!}
```
Bu durumda, eğer şu adrese giderseniz:
```
http://127.0.0.1:8000/items/foo?short=1
```
veya
```
http://127.0.0.1:8000/items/foo?short=True
```
veya
```
http://127.0.0.1:8000/items/foo?short=true
```
veya
```
http://127.0.0.1:8000/items/foo?short=on
```
veya
```
http://127.0.0.1:8000/items/foo?short=yes
```
veya adres, herhangi farklı bir harf varyasyonu içermesi durumuna rağmen (büyük harf, sadece baş harfi büyük kelime, vb.) fonksiyonunuz, `bool` tipli `short` parametresini `True` olarak algılayacaktır. Aksi halde `False` olarak algılanacaktır.
## Çoklu Yol ve Sorgu Parametreleri
**FastAPI** neyin ne olduğunu ayırt edebileceğinden dolayı aynı anda birden fazla yol ve sorgu parametresi tanımlayabilirsiniz.
Ve parametreleri, herhangi bir sıraya koymanıza da gerek yoktur.
İsimlerine göre belirleneceklerdir:
=== "Python 3.10+"
```Python hl_lines="6 8"
{!> ../../../docs_src/query_params/tutorial004_py310.py!}
```
=== "Python 3.8+"
```Python hl_lines="8 10"
{!> ../../../docs_src/query_params/tutorial004.py!}
```
## Zorunlu Sorgu Parametreleri
Türü yol olmayan bir parametre (şu ana kadar sadece sorgu parametrelerini gördük) için varsayılan değer tanımlarsanız o parametre zorunlu olmayacaktır.
Parametre için belirli bir değer atamak istemeyip parametrenin sadece isteğe bağlı olmasını istiyorsanız değerini `None` olarak atayabilirsiniz.
Fakat, bir sorgu parametresini zorunlu yapmak istiyorsanız varsayılan bir değer atamamanız yeterli olacaktır:
```Python hl_lines="6-7"
{!../../../docs_src/query_params/tutorial005.py!}
```
Burada `needy` parametresi `str` tipinden oluşan zorunlu bir sorgu parametresidir.
Eğer tarayıcınızda şu bağlantıyı:
```
http://127.0.0.1:8000/items/foo-item
```
...`needy` parametresini eklemeden açarsanız şuna benzer bir hata ile karşılaşırsınız:
```JSON
{
"detail": [
{
"type": "missing",
"loc": [
"query",
"needy"
],
"msg": "Field required",
"input": null,
"url": "https://errors.pydantic.dev/2.1/v/missing"
}
]
}
```
`needy` zorunlu bir parametre olduğundan dolayı bağlantıda tanımlanması gerekir:
```
http://127.0.0.1:8000/items/foo-item?needy=sooooneedy
```
...bu iş görür:
```JSON
{
"item_id": "foo-item",
"needy": "sooooneedy"
}
```
Ve elbette, bazı parametreleri zorunlu, bazılarını varsayılan değerli ve bazılarını tamamen opsiyonel olarak tanımlayabilirsiniz:
=== "Python 3.10+"
```Python hl_lines="8"
{!> ../../../docs_src/query_params/tutorial006_py310.py!}
```
=== "Python 3.8+"
```Python hl_lines="10"
{!> ../../../docs_src/query_params/tutorial006.py!}
```
Bu durumda, 3 tane sorgu parametresi var olacaktır:
* `needy`, zorunlu bir `str`.
* `skip`, varsayılan değeri `0` olan bir `int`.
* `limit`, isteğe bağlı bir `int`.
!!! tip "İpucu"
Ayrıca, [Yol Parametrelerinde](path-params.md#predefined-values){.internal-link target=_blank} de kullanıldığı şekilde `Enum` sınıfından faydalanabilirsiniz.

27
docs_src/dependencies/tutorial008c.py

@ -0,0 +1,27 @@
from fastapi import Depends, FastAPI, HTTPException
app = FastAPI()
class InternalError(Exception):
pass
def get_username():
try:
yield "Rick"
except InternalError:
print("Oops, we didn't raise again, Britney 😱")
@app.get("/items/{item_id}")
def get_item(item_id: str, username: str = Depends(get_username)):
if item_id == "portal-gun":
raise InternalError(
f"The portal gun is too dangerous to be owned by {username}"
)
if item_id != "plumbus":
raise HTTPException(
status_code=404, detail="Item not found, there's only a plumbus here"
)
return item_id

28
docs_src/dependencies/tutorial008c_an.py

@ -0,0 +1,28 @@
from fastapi import Depends, FastAPI, HTTPException
from typing_extensions import Annotated
app = FastAPI()
class InternalError(Exception):
pass
def get_username():
try:
yield "Rick"
except InternalError:
print("Oops, we didn't raise again, Britney 😱")
@app.get("/items/{item_id}")
def get_item(item_id: str, username: Annotated[str, Depends(get_username)]):
if item_id == "portal-gun":
raise InternalError(
f"The portal gun is too dangerous to be owned by {username}"
)
if item_id != "plumbus":
raise HTTPException(
status_code=404, detail="Item not found, there's only a plumbus here"
)
return item_id

29
docs_src/dependencies/tutorial008c_an_py39.py

@ -0,0 +1,29 @@
from typing import Annotated
from fastapi import Depends, FastAPI, HTTPException
app = FastAPI()
class InternalError(Exception):
pass
def get_username():
try:
yield "Rick"
except InternalError:
print("Oops, we didn't raise again, Britney 😱")
@app.get("/items/{item_id}")
def get_item(item_id: str, username: Annotated[str, Depends(get_username)]):
if item_id == "portal-gun":
raise InternalError(
f"The portal gun is too dangerous to be owned by {username}"
)
if item_id != "plumbus":
raise HTTPException(
status_code=404, detail="Item not found, there's only a plumbus here"
)
return item_id

28
docs_src/dependencies/tutorial008d.py

@ -0,0 +1,28 @@
from fastapi import Depends, FastAPI, HTTPException
app = FastAPI()
class InternalError(Exception):
pass
def get_username():
try:
yield "Rick"
except InternalError:
print("We don't swallow the internal error here, we raise again 😎")
raise
@app.get("/items/{item_id}")
def get_item(item_id: str, username: str = Depends(get_username)):
if item_id == "portal-gun":
raise InternalError(
f"The portal gun is too dangerous to be owned by {username}"
)
if item_id != "plumbus":
raise HTTPException(
status_code=404, detail="Item not found, there's only a plumbus here"
)
return item_id

29
docs_src/dependencies/tutorial008d_an.py

@ -0,0 +1,29 @@
from fastapi import Depends, FastAPI, HTTPException
from typing_extensions import Annotated
app = FastAPI()
class InternalError(Exception):
pass
def get_username():
try:
yield "Rick"
except InternalError:
print("We don't swallow the internal error here, we raise again 😎")
raise
@app.get("/items/{item_id}")
def get_item(item_id: str, username: Annotated[str, Depends(get_username)]):
if item_id == "portal-gun":
raise InternalError(
f"The portal gun is too dangerous to be owned by {username}"
)
if item_id != "plumbus":
raise HTTPException(
status_code=404, detail="Item not found, there's only a plumbus here"
)
return item_id

30
docs_src/dependencies/tutorial008d_an_py39.py

@ -0,0 +1,30 @@
from typing import Annotated
from fastapi import Depends, FastAPI, HTTPException
app = FastAPI()
class InternalError(Exception):
pass
def get_username():
try:
yield "Rick"
except InternalError:
print("We don't swallow the internal error here, we raise again 😎")
raise
@app.get("/items/{item_id}")
def get_item(item_id: str, username: Annotated[str, Depends(get_username)]):
if item_id == "portal-gun":
raise InternalError(
f"The portal gun is too dangerous to be owned by {username}"
)
if item_id != "plumbus":
raise HTTPException(
status_code=404, detail="Item not found, there's only a plumbus here"
)
return item_id

2
fastapi/__init__.py

@ -1,6 +1,6 @@
"""FastAPI framework, high performance, easy to learn, fast to code, ready for production"""
__version__ = "0.109.2"
__version__ = "0.110.0"
from starlette import status as status

108
fastapi/routing.py

@ -216,19 +216,14 @@ def get_request_handler(
actual_response_class = response_class
async def app(request: Request) -> Response:
exception_to_reraise: Optional[Exception] = None
response: Union[Response, None] = None
async with AsyncExitStack() as async_exit_stack:
# TODO: remove this scope later, after a few releases
# This scope fastapi_astack is no longer used by FastAPI, kept for
# compatibility, just in case
request.scope["fastapi_astack"] = async_exit_stack
async with AsyncExitStack() as file_stack:
try:
body: Any = None
if body_field:
if is_body_form:
body = await request.form()
async_exit_stack.push_async_callback(body.close)
file_stack.push_async_callback(body.close)
else:
body_bytes = await request.body()
if body_bytes:
@ -260,18 +255,17 @@ def get_request_handler(
],
body=e.doc,
)
exception_to_reraise = validation_error
raise validation_error from e
except HTTPException as e:
exception_to_reraise = e
except HTTPException:
# If a middleware raises an HTTPException, it should be raised again
raise
except Exception as e:
http_error = HTTPException(
status_code=400, detail="There was an error parsing the body"
)
exception_to_reraise = http_error
raise http_error from e
try:
errors: List[Any] = []
async with AsyncExitStack() as async_exit_stack:
solved_result = await solve_dependencies(
request=request,
dependant=dependant,
@ -280,59 +274,53 @@ def get_request_handler(
async_exit_stack=async_exit_stack,
)
values, errors, background_tasks, sub_response, _ = solved_result
except Exception as e:
exception_to_reraise = e
raise e
if not errors:
raw_response = await run_endpoint_function(
dependant=dependant, values=values, is_coroutine=is_coroutine
)
if isinstance(raw_response, Response):
if raw_response.background is None:
raw_response.background = background_tasks
response = raw_response
else:
response_args: Dict[str, Any] = {"background": background_tasks}
# If status_code was set, use it, otherwise use the default from the
# response class, in the case of redirect it's 307
current_status_code = (
status_code if status_code else sub_response.status_code
)
if current_status_code is not None:
response_args["status_code"] = current_status_code
if sub_response.status_code:
response_args["status_code"] = sub_response.status_code
content = await serialize_response(
field=response_field,
response_content=raw_response,
include=response_model_include,
exclude=response_model_exclude,
by_alias=response_model_by_alias,
exclude_unset=response_model_exclude_unset,
exclude_defaults=response_model_exclude_defaults,
exclude_none=response_model_exclude_none,
is_coroutine=is_coroutine,
)
response = actual_response_class(content, **response_args)
if not is_body_allowed_for_status_code(response.status_code):
response.body = b""
response.headers.raw.extend(sub_response.headers.raw)
if errors:
validation_error = RequestValidationError(
_normalize_errors(errors), body=body
)
exception_to_reraise = validation_error
raise validation_error
else:
try:
raw_response = await run_endpoint_function(
dependant=dependant, values=values, is_coroutine=is_coroutine
)
except Exception as e:
exception_to_reraise = e
raise e
if isinstance(raw_response, Response):
if raw_response.background is None:
raw_response.background = background_tasks
response = raw_response
else:
response_args: Dict[str, Any] = {"background": background_tasks}
# If status_code was set, use it, otherwise use the default from the
# response class, in the case of redirect it's 307
current_status_code = (
status_code if status_code else sub_response.status_code
)
if current_status_code is not None:
response_args["status_code"] = current_status_code
if sub_response.status_code:
response_args["status_code"] = sub_response.status_code
content = await serialize_response(
field=response_field,
response_content=raw_response,
include=response_model_include,
exclude=response_model_exclude,
by_alias=response_model_by_alias,
exclude_unset=response_model_exclude_unset,
exclude_defaults=response_model_exclude_defaults,
exclude_none=response_model_exclude_none,
is_coroutine=is_coroutine,
)
response = actual_response_class(content, **response_args)
if not is_body_allowed_for_status_code(response.status_code):
response.body = b""
response.headers.raw.extend(sub_response.headers.raw)
# This exception was possibly handled by the dependency but it should
# still bubble up so that the ServerErrorMiddleware can return a 500
# or the ExceptionMiddleware can catch and handle any other exceptions
if exception_to_reraise:
raise exception_to_reraise
assert response is not None, "An error occurred while generating the request"
if response is None:
raise FastAPIError(
"No response object was returned. There's a high chance that the "
"application code is raising an exception and a dependency with yield "
"has a block with a bare except, or a block with except Exception, "
"and is not raising the exception again. Read more about it in the "
"docs: https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/#dependencies-with-yield-and-except"
)
return response
return app

2
tests/test_dependency_contextmanager.py

@ -55,6 +55,7 @@ async def asyncgen_state_try(state: Dict[str, str] = Depends(get_state)):
yield state["/async_raise"]
except AsyncDependencyError:
errors.append("/async_raise")
raise
finally:
state["/async_raise"] = "asyncgen raise finalized"
@ -65,6 +66,7 @@ def generator_state_try(state: Dict[str, str] = Depends(get_state)):
yield state["/sync_raise"]
except SyncDependencyError:
errors.append("/sync_raise")
raise
finally:
state["/sync_raise"] = "generator raise finalized"

1
tests/test_dependency_normal_exceptions.py

@ -20,6 +20,7 @@ async def get_database():
fake_database.update(temp_database)
except HTTPException:
state["except"] = True
raise
finally:
state["finally"] = True

20
tests/test_tutorial/test_dependencies/test_tutorial008b_an_py39.py

@ -1,23 +1,33 @@
import pytest
from fastapi.testclient import TestClient
from docs_src.dependencies.tutorial008b_an import app
from ...utils import needs_py39
client = TestClient(app)
@pytest.fixture(name="client")
def get_client():
from docs_src.dependencies.tutorial008b_an_py39 import app
def test_get_no_item():
client = TestClient(app)
return client
@needs_py39
def test_get_no_item(client: TestClient):
response = client.get("/items/foo")
assert response.status_code == 404, response.text
assert response.json() == {"detail": "Item not found"}
def test_owner_error():
@needs_py39
def test_owner_error(client: TestClient):
response = client.get("/items/plumbus")
assert response.status_code == 400, response.text
assert response.json() == {"detail": "Owner error: Rick"}
def test_get_item():
@needs_py39
def test_get_item(client: TestClient):
response = client.get("/items/portal-gun")
assert response.status_code == 200, response.text
assert response.json() == {"description": "Gun to create portals", "owner": "Rick"}

38
tests/test_tutorial/test_dependencies/test_tutorial008c.py

@ -0,0 +1,38 @@
import pytest
from fastapi.exceptions import FastAPIError
from fastapi.testclient import TestClient
@pytest.fixture(name="client")
def get_client():
from docs_src.dependencies.tutorial008c import app
client = TestClient(app)
return client
def test_get_no_item(client: TestClient):
response = client.get("/items/foo")
assert response.status_code == 404, response.text
assert response.json() == {"detail": "Item not found, there's only a plumbus here"}
def test_get(client: TestClient):
response = client.get("/items/plumbus")
assert response.status_code == 200, response.text
assert response.json() == "plumbus"
def test_fastapi_error(client: TestClient):
with pytest.raises(FastAPIError) as exc_info:
client.get("/items/portal-gun")
assert "No response object was returned" in exc_info.value.args[0]
def test_internal_server_error():
from docs_src.dependencies.tutorial008c import app
client = TestClient(app, raise_server_exceptions=False)
response = client.get("/items/portal-gun")
assert response.status_code == 500, response.text
assert response.text == "Internal Server Error"

38
tests/test_tutorial/test_dependencies/test_tutorial008c_an.py

@ -0,0 +1,38 @@
import pytest
from fastapi.exceptions import FastAPIError
from fastapi.testclient import TestClient
@pytest.fixture(name="client")
def get_client():
from docs_src.dependencies.tutorial008c_an import app
client = TestClient(app)
return client
def test_get_no_item(client: TestClient):
response = client.get("/items/foo")
assert response.status_code == 404, response.text
assert response.json() == {"detail": "Item not found, there's only a plumbus here"}
def test_get(client: TestClient):
response = client.get("/items/plumbus")
assert response.status_code == 200, response.text
assert response.json() == "plumbus"
def test_fastapi_error(client: TestClient):
with pytest.raises(FastAPIError) as exc_info:
client.get("/items/portal-gun")
assert "No response object was returned" in exc_info.value.args[0]
def test_internal_server_error():
from docs_src.dependencies.tutorial008c_an import app
client = TestClient(app, raise_server_exceptions=False)
response = client.get("/items/portal-gun")
assert response.status_code == 500, response.text
assert response.text == "Internal Server Error"

44
tests/test_tutorial/test_dependencies/test_tutorial008c_an_py39.py

@ -0,0 +1,44 @@
import pytest
from fastapi.exceptions import FastAPIError
from fastapi.testclient import TestClient
from ...utils import needs_py39
@pytest.fixture(name="client")
def get_client():
from docs_src.dependencies.tutorial008c_an_py39 import app
client = TestClient(app)
return client
@needs_py39
def test_get_no_item(client: TestClient):
response = client.get("/items/foo")
assert response.status_code == 404, response.text
assert response.json() == {"detail": "Item not found, there's only a plumbus here"}
@needs_py39
def test_get(client: TestClient):
response = client.get("/items/plumbus")
assert response.status_code == 200, response.text
assert response.json() == "plumbus"
@needs_py39
def test_fastapi_error(client: TestClient):
with pytest.raises(FastAPIError) as exc_info:
client.get("/items/portal-gun")
assert "No response object was returned" in exc_info.value.args[0]
@needs_py39
def test_internal_server_error():
from docs_src.dependencies.tutorial008c_an_py39 import app
client = TestClient(app, raise_server_exceptions=False)
response = client.get("/items/portal-gun")
assert response.status_code == 500, response.text
assert response.text == "Internal Server Error"

41
tests/test_tutorial/test_dependencies/test_tutorial008d.py

@ -0,0 +1,41 @@
import pytest
from fastapi.testclient import TestClient
@pytest.fixture(name="client")
def get_client():
from docs_src.dependencies.tutorial008d import app
client = TestClient(app)
return client
def test_get_no_item(client: TestClient):
response = client.get("/items/foo")
assert response.status_code == 404, response.text
assert response.json() == {"detail": "Item not found, there's only a plumbus here"}
def test_get(client: TestClient):
response = client.get("/items/plumbus")
assert response.status_code == 200, response.text
assert response.json() == "plumbus"
def test_internal_error(client: TestClient):
from docs_src.dependencies.tutorial008d import InternalError
with pytest.raises(InternalError) as exc_info:
client.get("/items/portal-gun")
assert (
exc_info.value.args[0] == "The portal gun is too dangerous to be owned by Rick"
)
def test_internal_server_error():
from docs_src.dependencies.tutorial008d import app
client = TestClient(app, raise_server_exceptions=False)
response = client.get("/items/portal-gun")
assert response.status_code == 500, response.text
assert response.text == "Internal Server Error"

41
tests/test_tutorial/test_dependencies/test_tutorial008d_an.py

@ -0,0 +1,41 @@
import pytest
from fastapi.testclient import TestClient
@pytest.fixture(name="client")
def get_client():
from docs_src.dependencies.tutorial008d_an import app
client = TestClient(app)
return client
def test_get_no_item(client: TestClient):
response = client.get("/items/foo")
assert response.status_code == 404, response.text
assert response.json() == {"detail": "Item not found, there's only a plumbus here"}
def test_get(client: TestClient):
response = client.get("/items/plumbus")
assert response.status_code == 200, response.text
assert response.json() == "plumbus"
def test_internal_error(client: TestClient):
from docs_src.dependencies.tutorial008d_an import InternalError
with pytest.raises(InternalError) as exc_info:
client.get("/items/portal-gun")
assert (
exc_info.value.args[0] == "The portal gun is too dangerous to be owned by Rick"
)
def test_internal_server_error():
from docs_src.dependencies.tutorial008d_an import app
client = TestClient(app, raise_server_exceptions=False)
response = client.get("/items/portal-gun")
assert response.status_code == 500, response.text
assert response.text == "Internal Server Error"

47
tests/test_tutorial/test_dependencies/test_tutorial008d_an_py39.py

@ -0,0 +1,47 @@
import pytest
from fastapi.testclient import TestClient
from ...utils import needs_py39
@pytest.fixture(name="client")
def get_client():
from docs_src.dependencies.tutorial008d_an_py39 import app
client = TestClient(app)
return client
@needs_py39
def test_get_no_item(client: TestClient):
response = client.get("/items/foo")
assert response.status_code == 404, response.text
assert response.json() == {"detail": "Item not found, there's only a plumbus here"}
@needs_py39
def test_get(client: TestClient):
response = client.get("/items/plumbus")
assert response.status_code == 200, response.text
assert response.json() == "plumbus"
@needs_py39
def test_internal_error(client: TestClient):
from docs_src.dependencies.tutorial008d_an_py39 import InternalError
with pytest.raises(InternalError) as exc_info:
client.get("/items/portal-gun")
assert (
exc_info.value.args[0] == "The portal gun is too dangerous to be owned by Rick"
)
@needs_py39
def test_internal_server_error():
from docs_src.dependencies.tutorial008d_an_py39 import app
client = TestClient(app, raise_server_exceptions=False)
response = client.get("/items/portal-gun")
assert response.status_code == 500, response.text
assert response.text == "Internal Server Error"
Loading…
Cancel
Save