31 changed files with 1114 additions and 81 deletions
@ -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. 😎 |
@ -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> |
@ -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> |
@ -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 |
@ -0,0 +1,3 @@ |
|||||
|
# Encoder – `jsonable_encoder` |
||||
|
|
||||
|
::: fastapi.encoders.jsonable_encoder |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -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. |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -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 |
@ -1,23 +1,33 @@ |
|||||
|
import pytest |
||||
from fastapi.testclient import TestClient |
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") |
response = client.get("/items/foo") |
||||
assert response.status_code == 404, response.text |
assert response.status_code == 404, response.text |
||||
assert response.json() == {"detail": "Item not found"} |
assert response.json() == {"detail": "Item not found"} |
||||
|
|
||||
|
|
||||
def test_owner_error(): |
@needs_py39 |
||||
|
def test_owner_error(client: TestClient): |
||||
response = client.get("/items/plumbus") |
response = client.get("/items/plumbus") |
||||
assert response.status_code == 400, response.text |
assert response.status_code == 400, response.text |
||||
assert response.json() == {"detail": "Owner error: Rick"} |
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") |
response = client.get("/items/portal-gun") |
||||
assert response.status_code == 200, response.text |
assert response.status_code == 200, response.text |
||||
assert response.json() == {"description": "Gun to create portals", "owner": "Rick"} |
assert response.json() == {"description": "Gun to create portals", "owner": "Rick"} |
||||
|
@ -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" |
@ -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" |
@ -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" |
@ -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" |
@ -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" |
@ -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…
Reference in new issue