Query-Parameter und String-Validierungen¶
FastAPI ermöglicht es Ihnen, zusätzliche Informationen und Validierungen für Ihre Parameter zu deklarieren.
Nehmen wir diese Anwendung als Beispiel:
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/")
async def read_items(q: str | None = None):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
🤓 Other versions and variants
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/")
async def read_items(q: Union[str, None] = None):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Der Query-Parameter q
hat den Typ str | None
, das bedeutet, dass er vom Typ str
sein kann, aber auch None
, und tatsächlich ist der Defaultwert None
, sodass FastAPI weiß, dass er nicht erforderlich ist.
Hinweis
FastAPI erkennt, dass der Wert von q
nicht erforderlich ist, aufgrund des Defaultwertes = None
.
Die Verwendung von str | None
ermöglicht es Ihrem Editor, Ihnen bessere Unterstützung zu bieten und Fehler zu erkennen.
Zusätzliche Validierung¶
Wir werden sicherstellen, dass, obwohl q
optional ist, wann immer es bereitgestellt wird, seine Länge 50 Zeichen nicht überschreitet.
Query
und Annotated
importieren¶
Um dies zu erreichen, importieren Sie zuerst:
Query
vonfastapi
Annotated
vontyping
from typing import Annotated
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: Annotated[str | None, Query(max_length=50)] = None):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
🤓 Other versions and variants
from typing import Union
from fastapi import FastAPI, Query
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/")
async def read_items(q: Annotated[Union[str, None], Query(max_length=50)] = None):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Tip
Prefer to use the Annotated
version if possible.
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: str | None = Query(default=None, max_length=50)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Tip
Prefer to use the Annotated
version if possible.
from typing import Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: Union[str, None] = Query(default=None, max_length=50)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Info
FastAPI hat Unterstützung für Annotated
hinzugefügt (und begonnen, es zu empfehlen) in der Version 0.95.0.
Wenn Sie eine ältere Version haben, würden Sie Fehler erhalten, beim Versuch, Annotated
zu verwenden.
Stellen Sie sicher, dass Sie die FastAPI-Version aktualisieren, auf mindestens Version 0.95.1, bevor Sie Annotated
verwenden.
Verwenden von Annotated
im Typ für den q
-Parameter¶
Erinnern Sie sich, dass ich Ihnen zuvor in Python-Typen-Intro gesagt habe, dass Annotated
verwendet werden kann, um Metadaten zu Ihren Parametern hinzuzufügen?
Jetzt ist es soweit, dies mit FastAPI zu verwenden. 🚀
Wir hatten diese Typannotation:
q: str | None = None
q: Union[str, None] = None
Was wir tun werden, ist, dies mit Annotated
zu wrappen, sodass es zu:
q: Annotated[str | None] = None
q: Annotated[Union[str, None]] = None
Beide dieser Versionen bedeuten dasselbe: q
ist ein Parameter, der ein str
oder None
sein kann, und standardmäßig ist er None
.
Jetzt springen wir zu den spannenden Dingen. 🎉
Query
zu Annotated
im q
-Parameter hinzufügen¶
Da wir nun Annotated
haben, in das wir mehr Informationen (in diesem Fall einige zusätzliche Validierungen) einfügen können, fügen Sie Query
innerhalb von Annotated
hinzu und setzen Sie den Parameter max_length
auf 50
:
from typing import Annotated
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: Annotated[str | None, Query(max_length=50)] = None):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
🤓 Other versions and variants
from typing import Union
from fastapi import FastAPI, Query
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/")
async def read_items(q: Annotated[Union[str, None], Query(max_length=50)] = None):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Tip
Prefer to use the Annotated
version if possible.
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: str | None = Query(default=None, max_length=50)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Tip
Prefer to use the Annotated
version if possible.
from typing import Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: Union[str, None] = Query(default=None, max_length=50)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Beachten Sie, dass der Defaultwert weiterhin None
ist, so dass der Parameter weiterhin optional ist.
Aber jetzt, mit Query(max_length=50)
innerhalb von Annotated
, sagen wir FastAPI, dass wir eine zusätzliche Validierung für diesen Wert wünschen, wir wollen, dass er maximal 50 Zeichen hat. 😎
Tipp
Hier verwenden wir Query()
, weil dies ein Query-Parameter ist. Später werden wir andere wie Path()
, Body()
, Header()
, und Cookie()
sehen, die auch dieselben Argumente wie Query()
akzeptieren.
FastAPI wird nun:
- Die Daten validieren, um sicherzustellen, dass die Länge maximal 50 Zeichen beträgt
- Einen klaren Fehler für den Client anzeigen, wenn die Daten ungültig sind
- Den Parameter in der OpenAPI-Schema-Pfadoperation dokumentieren (sodass er in der automatischen Dokumentation angezeigt wird)
Alternative (alt): Query
als Defaultwert¶
Frühere Versionen von FastAPI (vor 0.95.0) erforderten, dass Sie Query
als den Defaultwert Ihres Parameters verwendeten, anstatt es innerhalb von Annotated
zu platzieren. Es besteht eine hohe Wahrscheinlichkeit, dass Sie Code sehen, der es so verwendet, also werde ich es Ihnen erklären.
Tipp
Für neuen Code und wann immer es möglich ist, verwenden Sie Annotated
wie oben erklärt. Es gibt mehrere Vorteile (unten erläutert) und keine Nachteile. 🍰
So würden Sie Query()
als den Defaultwert Ihres Funktionsparameters verwenden und den Parameter max_length
auf 50 setzen:
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: str | None = Query(default=None, max_length=50)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
🤓 Other versions and variants
from typing import Annotated
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: Annotated[str | None, Query(max_length=50)] = None):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
from typing import Union
from fastapi import FastAPI, Query
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/")
async def read_items(q: Annotated[Union[str, None], Query(max_length=50)] = None):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Tip
Prefer to use the Annotated
version if possible.
from typing import Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: Union[str, None] = Query(default=None, max_length=50)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Da wir in diesem Fall (ohne die Verwendung von Annotated
) den Defaultwert None
in der Funktion durch Query()
ersetzen müssen, müssen wir nun den Defaultwert mit dem Parameter Query(default=None)
setzen, er erfüllt den gleichen Zweck, diesen Defaultwert zu definieren (zumindest für FastAPI).
Also:
q: str | None = Query(default=None)
... macht den Parameter optional mit einem Defaultwert von None
, genauso wie:
q: str | None = None
Aber die Query
-Version deklariert ihn explizit als Query-Parameter.
Dann können wir mehr Parameter an Query
übergeben. In diesem Fall den max_length
-Parameter, der auf Strings angewendet wird:
q: str | None = Query(default=None, max_length=50)
Dies wird die Daten validieren, einen klaren Fehler anzeigen, wenn die Daten nicht gültig sind, und den Parameter in der OpenAPI-Schema-Pfadoperation dokumentieren.
Query
als Defaultwert oder in Annotated
¶
Beachten Sie, dass wenn Sie Query
innerhalb von Annotated
verwenden, Sie den default
-Parameter für Query
nicht verwenden dürfen.
Setzen Sie stattdessen den tatsächlichen Defaultwert des Funktionsparameters. Andernfalls wäre es inkonsistent.
Zum Beispiel ist das nicht erlaubt:
q: Annotated[str, Query(default="rick")] = "morty"
... denn es ist nicht klar, ob der Defaultwert "rick"
oder "morty"
sein soll.
Sie würden also (bevorzugt) schreiben:
q: Annotated[str, Query()] = "rick"
... oder in älteren Codebasen finden Sie:
q: str = Query(default="rick")
Vorzüge von Annotated
¶
Es wird empfohlen, Annotated
zu verwenden, anstelle des Defaultwertes in Funktionsparametern, es ist aus mehreren Gründen besser. 🤓
Der Defaultwert des Funktionsparameters ist der tatsächliche Defaultwert, das ist in der Regel intuitiver mit Python. 😌
Sie könnten diese gleiche Funktion in anderen Stellen ohne FastAPI aufrufen, und es würde wie erwartet funktionieren. Wenn es einen erforderlichen Parameter gibt (ohne Defaultwert), wird Ihr Editor Ihnen dies mit einem Fehler mitteilen, außerdem wird Python sich beschweren, wenn Sie es ausführen, ohne den erforderlichen Parameter zu übergeben.
Wenn Sie Annotated
nicht verwenden und stattdessen die (alte) Defaultwert-Stilform verwenden, müssen Sie sich daran erinnern, die Argumente der Funktion zu übergeben, wenn Sie diese Funktion ohne FastAPI in anderen Stellen aufrufen. Ansonsten sind die Werte anders als erwartet (z. B. QueryInfo
oder etwas Ähnliches statt str
). Ihr Editor kann Ihnen nicht helfen, und Python wird die Funktion ohne Klagen ausführen und sich nur beschweren wenn die Operationen innerhalb auf einen Fehler stoßen.
Da Annotated
mehr als eine Metadaten-Annotation haben kann, könnten Sie dieselbe Funktion sogar mit anderen Tools verwenden, wie z. B. Typer. 🚀
Mehr Validierungen hinzufügen¶
Sie können auch einen min_length
-Parameter hinzufügen:
from typing import Annotated
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Annotated[str | None, Query(min_length=3, max_length=50)] = None,
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
🤓 Other versions and variants
from typing import Annotated, Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Annotated[Union[str, None], Query(min_length=3, max_length=50)] = None,
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
from typing import Union
from fastapi import FastAPI, Query
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Annotated[Union[str, None], Query(min_length=3, max_length=50)] = None,
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Tip
Prefer to use the Annotated
version if possible.
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: str | None = Query(default=None, min_length=3, max_length=50)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Tip
Prefer to use the Annotated
version if possible.
from typing import Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Union[str, None] = Query(default=None, min_length=3, max_length=50),
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Reguläre Ausdrücke hinzufügen¶
Sie können einen regulären Ausdruck pattern
definieren, mit dem der Parameter übereinstimmen muss:
from typing import Annotated
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Annotated[
str | None, Query(min_length=3, max_length=50, pattern="^fixedquery$")
] = None,
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
🤓 Other versions and variants
from typing import Annotated, Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Annotated[
Union[str, None], Query(min_length=3, max_length=50, pattern="^fixedquery$")
] = None,
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
from typing import Union
from fastapi import FastAPI, Query
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Annotated[
Union[str, None], Query(min_length=3, max_length=50, pattern="^fixedquery$")
] = None,
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Tip
Prefer to use the Annotated
version if possible.
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
q: str | None = Query(
default=None, min_length=3, max_length=50, pattern="^fixedquery$"
),
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Tip
Prefer to use the Annotated
version if possible.
from typing import Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Union[str, None] = Query(
default=None, min_length=3, max_length=50, pattern="^fixedquery$"
),
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Dieses spezielle Suchmuster im regulären Ausdruck überprüft, dass der erhaltene Parameterwert:
^
: mit den nachfolgenden Zeichen beginnt, keine Zeichen davor hat.fixedquery
: den exakten Textfixedquery
hat.$
: dort endet, keine weiteren Zeichen nachfixedquery
hat.
Wenn Sie sich mit all diesen „regulärer Ausdruck“-Ideen verloren fühlen, keine Sorge. Sie sind ein schwieriges Thema für viele Menschen. Sie können noch viele Dinge tun, ohne reguläre Ausdrücke direkt zu benötigen.
Aber nun wissen Sie, dass Sie sie in FastAPI immer dann verwenden können, wenn Sie sie brauchen.
Pydantic v1 regex
statt pattern
¶
Vor Pydantic Version 2 und FastAPI 0.100.0, hieß der Parameter regex
statt pattern
, aber das ist jetzt obsolet.
Sie könnten immer noch Code sehen, der den alten Namen verwendet:
from typing import Annotated
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Annotated[
str | None, Query(min_length=3, max_length=50, regex="^fixedquery$")
] = None,
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Beachten Sie aber, dass das obsolet ist und auf den neuen Parameter pattern
aktualisiert werden sollte. 🤓
Defaultwerte¶
Natürlich können Sie Defaultwerte verwenden, die nicht None
sind.
Nehmen wir an, Sie möchten, dass der q
Query-Parameter eine min_length
von 3
hat und einen Defaultwert von "fixedquery"
:
from typing import Annotated
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: Annotated[str, Query(min_length=3)] = "fixedquery"):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
🤓 Other versions and variants
from fastapi import FastAPI, Query
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/")
async def read_items(q: Annotated[str, Query(min_length=3)] = "fixedquery"):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Tip
Prefer to use the Annotated
version if possible.
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: str = Query(default="fixedquery", min_length=3)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Hinweis
Ein Defaultwert irgendeines Typs, einschließlich None
, macht den Parameter optional (nicht erforderlich).
Erforderliche Parameter¶
Wenn wir keine weiteren Validierungen oder Metadaten deklarieren müssen, können wir den q
Query-Parameter erforderlich machen, indem wir einfach keinen Defaultwert deklarieren, wie:
q: str
statt:
q: str | None = None
Aber jetzt deklarieren wir es mit Query
, zum Beispiel so:
q: Annotated[str | None, Query(min_length=3)] = None
Wenn Sie einen Wert als erforderlich deklarieren müssen, während Sie Query
verwenden, deklarieren Sie einfach keinen Defaultwert:
from typing import Annotated
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: Annotated[str, Query(min_length=3)]):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
🤓 Other versions and variants
from fastapi import FastAPI, Query
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/")
async def read_items(q: Annotated[str, Query(min_length=3)]):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Tip
Prefer to use the Annotated
version if possible.
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: str = Query(min_length=3)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Erforderlich, kann None
sein¶
Sie können deklarieren, dass ein Parameter None
akzeptieren kann, aber trotzdem erforderlich ist. Dadurch müssten Clients den Wert senden, selbst wenn der Wert None
ist.
Um das zu tun, können Sie deklarieren, dass None
ein gültiger Typ ist, einfach indem Sie keinen Defaultwert deklarieren:
from typing import Annotated
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: Annotated[str | None, Query(min_length=3)]):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
🤓 Other versions and variants
from typing import Annotated, Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: Annotated[Union[str, None], Query(min_length=3)]):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
from typing import Union
from fastapi import FastAPI, Query
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/")
async def read_items(q: Annotated[Union[str, None], Query(min_length=3)]):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Tip
Prefer to use the Annotated
version if possible.
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: str | None = Query(min_length=3)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Tip
Prefer to use the Annotated
version if possible.
from typing import Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: Union[str, None] = Query(min_length=3)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Query-Parameter-Liste / Mehrere Werte¶
Wenn Sie einen Query-Parameter explizit mit Query
definieren, können Sie ihn auch so deklarieren, dass er eine Liste von Werten empfängt, oder anders gesagt, dass er mehrere Werte empfangen kann.
Um zum Beispiel einen Query-Parameter q
zu deklarieren, der mehrmals in der URL vorkommen kann, schreiben Sie:
from typing import Annotated
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: Annotated[list[str] | None, Query()] = None):
query_items = {"q": q}
return query_items
🤓 Other versions and variants
from typing import Annotated, Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: Annotated[Union[list[str], None], Query()] = None):
query_items = {"q": q}
return query_items
from typing import List, Union
from fastapi import FastAPI, Query
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/")
async def read_items(q: Annotated[Union[List[str], None], Query()] = None):
query_items = {"q": q}
return query_items
Tip
Prefer to use the Annotated
version if possible.
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: list[str] | None = Query(default=None)):
query_items = {"q": q}
return query_items
Tip
Prefer to use the Annotated
version if possible.
from typing import Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: Union[list[str], None] = Query(default=None)):
query_items = {"q": q}
return query_items
Tip
Prefer to use the Annotated
version if possible.
from typing import List, Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: Union[List[str], None] = Query(default=None)):
query_items = {"q": q}
return query_items
Dann, mit einer URL wie:
http://localhost:8000/items/?q=foo&q=bar
würden Sie die mehreren q
-Query-Parameter-Werte (foo
und bar
) in einer Python-list
in Ihrer Pfadoperation-Funktion im Funktionsparameter q
erhalten.
So wäre die Response zu dieser URL:
{
"q": [
"foo",
"bar"
]
}
Tipp
Um einen Query-Parameter mit einem Typ list
zu deklarieren, wie im obigen Beispiel, müssen Sie explizit Query
verwenden, da er andernfalls als Requestbody interpretiert würde.
Die interaktive API-Dokumentation wird entsprechend aktualisiert, um mehrere Werte zu erlauben:
Query-Parameter-Liste / Mehrere Werte mit Defaults¶
Sie können auch eine Default-list
von Werten definieren, wenn keine bereitgestellt werden:
from typing import Annotated
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: Annotated[list[str], Query()] = ["foo", "bar"]):
query_items = {"q": q}
return query_items
🤓 Other versions and variants
from typing import List
from fastapi import FastAPI, Query
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/")
async def read_items(q: Annotated[List[str], Query()] = ["foo", "bar"]):
query_items = {"q": q}
return query_items
Tip
Prefer to use the Annotated
version if possible.
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: list[str] = Query(default=["foo", "bar"])):
query_items = {"q": q}
return query_items
Tip
Prefer to use the Annotated
version if possible.
from typing import List
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: List[str] = Query(default=["foo", "bar"])):
query_items = {"q": q}
return query_items
Wenn Sie zu:
http://localhost:8000/items/
gehen, wird der Default für q
sein: ["foo", "bar"]
, und Ihre Response wird sein:
{
"q": [
"foo",
"bar"
]
}
Nur list
verwenden¶
Sie können auch list
direkt verwenden, anstelle von list[str]
:
from typing import Annotated
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: Annotated[list, Query()] = []):
query_items = {"q": q}
return query_items
🤓 Other versions and variants
from fastapi import FastAPI, Query
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/")
async def read_items(q: Annotated[list, Query()] = []):
query_items = {"q": q}
return query_items
Tip
Prefer to use the Annotated
version if possible.
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: list = Query(default=[])):
query_items = {"q": q}
return query_items
Hinweis
Beachten Sie, dass FastAPI in diesem Fall den Inhalt der Liste nicht überprüft.
Zum Beispiel würde list[int]
überprüfen (und dokumentieren), dass der Inhalt der Liste Ganzzahlen sind. Aber list
alleine würde das nicht.
Mehr Metadaten deklarieren¶
Sie können mehr Informationen über den Parameter hinzufügen.
Diese Informationen werden in das generierte OpenAPI aufgenommen und von den Dokumentationsoberflächen und externen Tools verwendet.
Hinweis
Beachten Sie, dass verschiedene Tools möglicherweise unterschiedliche Unterstützungslevels für OpenAPI haben.
Einige davon könnten noch nicht alle zusätzlichen Informationen anzuzeigen, die Sie erklärten, obwohl in den meisten Fällen die fehlende Funktionalität bereits in der Entwicklung geplant ist.
Sie können einen title
hinzufügen:
from typing import Annotated
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Annotated[str | None, Query(title="Query string", min_length=3)] = None,
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
🤓 Other versions and variants
from typing import Annotated, Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Annotated[Union[str, None], Query(title="Query string", min_length=3)] = None,
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
from typing import Union
from fastapi import FastAPI, Query
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Annotated[Union[str, None], Query(title="Query string", min_length=3)] = None,
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Tip
Prefer to use the Annotated
version if possible.
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
q: str | None = Query(default=None, title="Query string", min_length=3),
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Tip
Prefer to use the Annotated
version if possible.
from typing import Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Union[str, None] = Query(default=None, title="Query string", min_length=3),
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Und eine description
:
from typing import Annotated
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Annotated[
str | None,
Query(
title="Query string",
description="Query string for the items to search in the database that have a good match",
min_length=3,
),
] = None,
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
🤓 Other versions and variants
from typing import Annotated, Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Annotated[
Union[str, None],
Query(
title="Query string",
description="Query string for the items to search in the database that have a good match",
min_length=3,
),
] = None,
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
from typing import Union
from fastapi import FastAPI, Query
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Annotated[
Union[str, None],
Query(
title="Query string",
description="Query string for the items to search in the database that have a good match",
min_length=3,
),
] = None,
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Tip
Prefer to use the Annotated
version if possible.
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
q: str | None = Query(
default=None,
title="Query string",
description="Query string for the items to search in the database that have a good match",
min_length=3,
),
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Tip
Prefer to use the Annotated
version if possible.
from typing import Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Union[str, None] = Query(
default=None,
title="Query string",
description="Query string for the items to search in the database that have a good match",
min_length=3,
),
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Alias-Parameter¶
Stellen Sie sich vor, Sie möchten, dass der Parameter item-query
ist.
Wie in:
http://127.0.0.1:8000/items/?item-query=foobaritems
Aber item-query
ist kein gültiger Name für eine Variable in Python.
Der am ähnlichsten wäre item_query
.
Aber Sie benötigen dennoch, dass er genau item-query
ist ...
Dann können Sie ein alias
deklarieren, und dieser Alias wird verwendet, um den Parameterwert zu finden:
from typing import Annotated
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: Annotated[str | None, Query(alias="item-query")] = None):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
🤓 Other versions and variants
from typing import Annotated, Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: Annotated[Union[str, None], Query(alias="item-query")] = None):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
from typing import Union
from fastapi import FastAPI, Query
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/")
async def read_items(q: Annotated[Union[str, None], Query(alias="item-query")] = None):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Tip
Prefer to use the Annotated
version if possible.
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: str | None = Query(default=None, alias="item-query")):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Tip
Prefer to use the Annotated
version if possible.
from typing import Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: Union[str, None] = Query(default=None, alias="item-query")):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Parameter als deprecatet ausweisen¶
Nehmen wir an, Ihnen gefällt dieser Parameter nicht mehr.
Sie müssen ihn eine Weile dort belassen, da es Clients gibt, die ihn verwenden, aber Sie möchten, dass die Dokumentation ihn klar als deprecatet anzeigt.
Dann übergeben Sie den Parameter deprecated=True
an Query
:
from typing import Annotated
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Annotated[
str | None,
Query(
alias="item-query",
title="Query string",
description="Query string for the items to search in the database that have a good match",
min_length=3,
max_length=50,
pattern="^fixedquery$",
deprecated=True,
),
] = None,
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
🤓 Other versions and variants
from typing import Annotated, Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Annotated[
Union[str, None],
Query(
alias="item-query",
title="Query string",
description="Query string for the items to search in the database that have a good match",
min_length=3,
max_length=50,
pattern="^fixedquery$",
deprecated=True,
),
] = None,
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
from typing import Union
from fastapi import FastAPI, Query
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Annotated[
Union[str, None],
Query(
alias="item-query",
title="Query string",
description="Query string for the items to search in the database that have a good match",
min_length=3,
max_length=50,
pattern="^fixedquery$",
deprecated=True,
),
] = None,
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Tip
Prefer to use the Annotated
version if possible.
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
q: str | None = Query(
default=None,
alias="item-query",
title="Query string",
description="Query string for the items to search in the database that have a good match",
min_length=3,
max_length=50,
pattern="^fixedquery$",
deprecated=True,
),
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Tip
Prefer to use the Annotated
version if possible.
from typing import Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
q: Union[str, None] = Query(
default=None,
alias="item-query",
title="Query string",
description="Query string for the items to search in the database that have a good match",
min_length=3,
max_length=50,
pattern="^fixedquery$",
deprecated=True,
),
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
Die Dokumentation wird es so anzeigen:
Parameter von OpenAPI ausschließen¶
Um einen Query-Parameter aus dem generierten OpenAPI-Schema auszuschließen (und somit aus den automatischen Dokumentationssystemen), setzen Sie den Parameter include_in_schema
von Query
auf False
:
from typing import Annotated
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
hidden_query: Annotated[str | None, Query(include_in_schema=False)] = None,
):
if hidden_query:
return {"hidden_query": hidden_query}
else:
return {"hidden_query": "Not found"}
🤓 Other versions and variants
from typing import Annotated, Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
hidden_query: Annotated[Union[str, None], Query(include_in_schema=False)] = None,
):
if hidden_query:
return {"hidden_query": hidden_query}
else:
return {"hidden_query": "Not found"}
from typing import Union
from fastapi import FastAPI, Query
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/")
async def read_items(
hidden_query: Annotated[Union[str, None], Query(include_in_schema=False)] = None,
):
if hidden_query:
return {"hidden_query": hidden_query}
else:
return {"hidden_query": "Not found"}
Tip
Prefer to use the Annotated
version if possible.
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
hidden_query: str | None = Query(default=None, include_in_schema=False),
):
if hidden_query:
return {"hidden_query": hidden_query}
else:
return {"hidden_query": "Not found"}
Tip
Prefer to use the Annotated
version if possible.
from typing import Union
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
hidden_query: Union[str, None] = Query(default=None, include_in_schema=False),
):
if hidden_query:
return {"hidden_query": hidden_query}
else:
return {"hidden_query": "Not found"}
Benutzerdefinierte Validierung¶
Es kann Fälle geben, in denen Sie eine benutzerdefinierte Validierung durchführen müssen, die nicht mit den oben gezeigten Parametern durchgeführt werden kann.
In diesen Fällen können Sie eine benutzerdefinierte Validierungsfunktion verwenden, die nach der normalen Validierung angewendet wird (z. B. nach der Validierung, dass der Wert ein str
ist).
Sie können dies mit Pydantic's AfterValidator
innerhalb von Annotated
erreichen.
Tipp
Pydantic unterstützt auch BeforeValidator
und andere. 🤓
Zum Beispiel überprüft dieser benutzerdefinierte Validator, ob die Artikel-ID mit isbn-
für eine ISBN-Buchnummer oder mit imdb-
für eine IMDB-Film-URL-ID beginnt:
import random
from typing import Annotated
from fastapi import FastAPI
from pydantic import AfterValidator
app = FastAPI()
data = {
"isbn-9781529046137": "The Hitchhiker's Guide to the Galaxy",
"imdb-tt0371724": "The Hitchhiker's Guide to the Galaxy",
"isbn-9781439512982": "Isaac Asimov: The Complete Stories, Vol. 2",
}
def check_valid_id(id: str):
if not id.startswith(("isbn-", "imdb-")):
raise ValueError('Invalid ID format, it must start with "isbn-" or "imdb-"')
return id
@app.get("/items/")
async def read_items(
id: Annotated[str | None, AfterValidator(check_valid_id)] = None,
):
if id:
item = data.get(id)
else:
id, item = random.choice(list(data.items()))
return {"id": id, "name": item}
🤓 Other versions and variants
import random
from typing import Annotated, Union
from fastapi import FastAPI
from pydantic import AfterValidator
app = FastAPI()
data = {
"isbn-9781529046137": "The Hitchhiker's Guide to the Galaxy",
"imdb-tt0371724": "The Hitchhiker's Guide to the Galaxy",
"isbn-9781439512982": "Isaac Asimov: The Complete Stories, Vol. 2",
}
def check_valid_id(id: str):
if not id.startswith(("isbn-", "imdb-")):
raise ValueError('Invalid ID format, it must start with "isbn-" or "imdb-"')
return id
@app.get("/items/")
async def read_items(
id: Annotated[Union[str, None], AfterValidator(check_valid_id)] = None,
):
if id:
item = data.get(id)
else:
id, item = random.choice(list(data.items()))
return {"id": id, "name": item}
import random
from typing import Union
from fastapi import FastAPI
from pydantic import AfterValidator
from typing_extensions import Annotated
app = FastAPI()
data = {
"isbn-9781529046137": "The Hitchhiker's Guide to the Galaxy",
"imdb-tt0371724": "The Hitchhiker's Guide to the Galaxy",
"isbn-9781439512982": "Isaac Asimov: The Complete Stories, Vol. 2",
}
def check_valid_id(id: str):
if not id.startswith(("isbn-", "imdb-")):
raise ValueError('Invalid ID format, it must start with "isbn-" or "imdb-"')
return id
@app.get("/items/")
async def read_items(
id: Annotated[Union[str, None], AfterValidator(check_valid_id)] = None,
):
if id:
item = data.get(id)
else:
id, item = random.choice(list(data.items()))
return {"id": id, "name": item}
Info
Dies ist verfügbar seit Pydantic Version 2 oder höher. 😎
Tipp
Wenn Sie irgendeine Art von Validierung durchführen müssen, die eine Kommunikation mit einer externen Komponente erfordert, wie z. B. einer Datenbank oder einer anderen API, sollten Sie stattdessen FastAPI-Abhängigkeiten verwenden. Sie werden diese später kennenlernen.
Diese benutzerdefinierten Validatoren sind für Dinge gedacht, die einfach mit denselben Daten überprüft werden können, die im Request bereitgestellt werden.
Dieses Codebeispiel verstehen¶
Der wichtige Punkt ist einfach die Verwendung von AfterValidator
mit einer Funktion innerhalb von Annotated
. Fühlen Sie sich frei, diesen Teil zu überspringen. 🤸
Aber wenn Sie neugierig auf dieses spezielle Codebeispiel sind und immer noch Spaß haben, hier sind einige zusätzliche Details.
Zeichenkette mit value.startswith()
¶
Haben Sie bemerkt? Eine Zeichenkette mit value.startswith()
kann ein Tuple übernehmen, und es wird jeden Wert im Tuple überprüfen:
# Code above omitted 👆
def check_valid_id(id: str):
if not id.startswith(("isbn-", "imdb-")):
raise ValueError('Invalid ID format, it must start with "isbn-" or "imdb-"')
return id
# Code below omitted 👇
👀 Full file preview
import random
from typing import Annotated
from fastapi import FastAPI
from pydantic import AfterValidator
app = FastAPI()
data = {
"isbn-9781529046137": "The Hitchhiker's Guide to the Galaxy",
"imdb-tt0371724": "The Hitchhiker's Guide to the Galaxy",
"isbn-9781439512982": "Isaac Asimov: The Complete Stories, Vol. 2",
}
def check_valid_id(id: str):
if not id.startswith(("isbn-", "imdb-")):
raise ValueError('Invalid ID format, it must start with "isbn-" or "imdb-"')
return id
@app.get("/items/")
async def read_items(
id: Annotated[str | None, AfterValidator(check_valid_id)] = None,
):
if id:
item = data.get(id)
else:
id, item = random.choice(list(data.items()))
return {"id": id, "name": item}
🤓 Other versions and variants
import random
from typing import Annotated, Union
from fastapi import FastAPI
from pydantic import AfterValidator
app = FastAPI()
data = {
"isbn-9781529046137": "The Hitchhiker's Guide to the Galaxy",
"imdb-tt0371724": "The Hitchhiker's Guide to the Galaxy",
"isbn-9781439512982": "Isaac Asimov: The Complete Stories, Vol. 2",
}
def check_valid_id(id: str):
if not id.startswith(("isbn-", "imdb-")):
raise ValueError('Invalid ID format, it must start with "isbn-" or "imdb-"')
return id
@app.get("/items/")
async def read_items(
id: Annotated[Union[str, None], AfterValidator(check_valid_id)] = None,
):
if id:
item = data.get(id)
else:
id, item = random.choice(list(data.items()))
return {"id": id, "name": item}
import random
from typing import Union
from fastapi import FastAPI
from pydantic import AfterValidator
from typing_extensions import Annotated
app = FastAPI()
data = {
"isbn-9781529046137": "The Hitchhiker's Guide to the Galaxy",
"imdb-tt0371724": "The Hitchhiker's Guide to the Galaxy",
"isbn-9781439512982": "Isaac Asimov: The Complete Stories, Vol. 2",
}
def check_valid_id(id: str):
if not id.startswith(("isbn-", "imdb-")):
raise ValueError('Invalid ID format, it must start with "isbn-" or "imdb-"')
return id
@app.get("/items/")
async def read_items(
id: Annotated[Union[str, None], AfterValidator(check_valid_id)] = None,
):
if id:
item = data.get(id)
else:
id, item = random.choice(list(data.items()))
return {"id": id, "name": item}
Ein zufälliges Item¶
Mit data.items()
erhalten wir ein iterierbares Objekt mit Tupeln, die Schlüssel und Wert für jedes Dictionary-Element enthalten.
Wir konvertieren dieses iterierbare Objekt mit list(data.items())
in eine richtige list
.
Dann können wir mit random.choice()
einen zufälligen Wert aus der Liste erhalten, also bekommen wir ein Tuple mit (id, name)
. Es wird etwas wie ("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")
sein.
Dann weisen wir diese beiden Werte des Tupels den Variablen id
und name
zu.
Wenn der Benutzer also keine Artikel-ID bereitgestellt hat, erhält er trotzdem einen zufälligen Vorschlag.
... wir tun all dies in einer einzelnen einfachen Zeile. 🤯 Lieben Sie nicht auch Python? 🐍
# Code above omitted 👆
@app.get("/items/")
async def read_items(
id: Annotated[str | None, AfterValidator(check_valid_id)] = None,
):
if id:
item = data.get(id)
else:
id, item = random.choice(list(data.items()))
return {"id": id, "name": item}
👀 Full file preview
import random
from typing import Annotated
from fastapi import FastAPI
from pydantic import AfterValidator
app = FastAPI()
data = {
"isbn-9781529046137": "The Hitchhiker's Guide to the Galaxy",
"imdb-tt0371724": "The Hitchhiker's Guide to the Galaxy",
"isbn-9781439512982": "Isaac Asimov: The Complete Stories, Vol. 2",
}
def check_valid_id(id: str):
if not id.startswith(("isbn-", "imdb-")):
raise ValueError('Invalid ID format, it must start with "isbn-" or "imdb-"')
return id
@app.get("/items/")
async def read_items(
id: Annotated[str | None, AfterValidator(check_valid_id)] = None,
):
if id:
item = data.get(id)
else:
id, item = random.choice(list(data.items()))
return {"id": id, "name": item}
🤓 Other versions and variants
import random
from typing import Annotated, Union
from fastapi import FastAPI
from pydantic import AfterValidator
app = FastAPI()
data = {
"isbn-9781529046137": "The Hitchhiker's Guide to the Galaxy",
"imdb-tt0371724": "The Hitchhiker's Guide to the Galaxy",
"isbn-9781439512982": "Isaac Asimov: The Complete Stories, Vol. 2",
}
def check_valid_id(id: str):
if not id.startswith(("isbn-", "imdb-")):
raise ValueError('Invalid ID format, it must start with "isbn-" or "imdb-"')
return id
@app.get("/items/")
async def read_items(
id: Annotated[Union[str, None], AfterValidator(check_valid_id)] = None,
):
if id:
item = data.get(id)
else:
id, item = random.choice(list(data.items()))
return {"id": id, "name": item}
import random
from typing import Union
from fastapi import FastAPI
from pydantic import AfterValidator
from typing_extensions import Annotated
app = FastAPI()
data = {
"isbn-9781529046137": "The Hitchhiker's Guide to the Galaxy",
"imdb-tt0371724": "The Hitchhiker's Guide to the Galaxy",
"isbn-9781439512982": "Isaac Asimov: The Complete Stories, Vol. 2",
}
def check_valid_id(id: str):
if not id.startswith(("isbn-", "imdb-")):
raise ValueError('Invalid ID format, it must start with "isbn-" or "imdb-"')
return id
@app.get("/items/")
async def read_items(
id: Annotated[Union[str, None], AfterValidator(check_valid_id)] = None,
):
if id:
item = data.get(id)
else:
id, item = random.choice(list(data.items()))
return {"id": id, "name": item}
Zusammenfassung¶
Sie können zusätzliche Validierungen und Metadaten für Ihre Parameter deklarieren.
Allgemeine Validierungen und Metadaten:
alias
title
description
deprecated
Validierungen, die spezifisch für Strings sind:
min_length
max_length
pattern
Benutzerdefinierte Validierungen mit AfterValidator
.
In diesen Beispielen haben Sie gesehen, wie Sie Validierungen für str
-Werte deklarieren.
Sehen Sie sich die nächsten Kapitel an, um zu erfahren, wie Sie Validierungen für andere Typen, wie z. B. Zahlen, deklarieren.