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 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"} |
|||
|
@ -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