Zum Inhalt

Pfad-Parameter und Validierung von Zahlen

So wie Sie mit Query für Query-Parameter zusätzliche Validierungen und Metadaten hinzufügen können, können Sie das mittels Path auch für Pfad-Parameter tun.

Path importieren

Importieren Sie zuerst Path von fastapi, und importieren Sie Annotated.

from typing import Annotated

from fastapi import FastAPI, Path, Query

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get")],
    q: Annotated[str | None, Query(alias="item-query")] = None,
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results
🤓 Other versions and variants
from typing import Annotated, Union

from fastapi import FastAPI, Path, Query

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get")],
    q: Annotated[Union[str, None], Query(alias="item-query")] = None,
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results
from typing import Union

from fastapi import FastAPI, Path, Query
from typing_extensions import Annotated

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get")],
    q: Annotated[Union[str, None], Query(alias="item-query")] = None,
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Path, Query

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: int = Path(title="The ID of the item to get"),
    q: str | None = Query(default=None, alias="item-query"),
):
    results = {"item_id": item_id}
    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, Path, Query

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: int = Path(title="The ID of the item to get"),
    q: Union[str, None] = Query(default=None, alias="item-query"),
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

Info

FastAPI unterstützt (und empfiehlt die Verwendung von) Annotated seit Version 0.95.0.

Wenn Sie eine ältere Version haben, werden Sie Fehler angezeigt bekommen, wenn Sie versuchen, Annotated zu verwenden.

Bitte aktualisieren Sie FastAPI daher mindestens zu Version 0.95.1, bevor Sie Annotated verwenden.

Metadaten deklarieren

Sie können die gleichen Parameter deklarieren wie für Query.

Um zum Beispiel einen title-Metadaten-Wert für den Pfad-Parameter item_id zu deklarieren, schreiben Sie:

from typing import Annotated

from fastapi import FastAPI, Path, Query

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get")],
    q: Annotated[str | None, Query(alias="item-query")] = None,
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results
🤓 Other versions and variants
from typing import Annotated, Union

from fastapi import FastAPI, Path, Query

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get")],
    q: Annotated[Union[str, None], Query(alias="item-query")] = None,
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results
from typing import Union

from fastapi import FastAPI, Path, Query
from typing_extensions import Annotated

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get")],
    q: Annotated[Union[str, None], Query(alias="item-query")] = None,
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Path, Query

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: int = Path(title="The ID of the item to get"),
    q: str | None = Query(default=None, alias="item-query"),
):
    results = {"item_id": item_id}
    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, Path, Query

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: int = Path(title="The ID of the item to get"),
    q: Union[str, None] = Query(default=None, alias="item-query"),
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

Hinweis

Ein Pfad-Parameter ist immer erforderlich, weil er Teil des Pfads sein muss.

Sie sollten ihn daher mit ... deklarieren, um ihn als erforderlich auszuzeichnen.

Doch selbst wenn Sie ihn mit None deklarieren, oder einen Defaultwert setzen, bewirkt das nichts, er bleibt immer erforderlich.

Sortieren Sie die Parameter, wie Sie möchten

Tipp

Wenn Sie Annotated verwenden, ist das folgende nicht so wichtig / nicht notwendig.

Nehmen wir an, Sie möchten den Query-Parameter q als erforderlichen str deklarieren.

Und Sie müssen sonst nichts anderes für den Parameter deklarieren, Sie brauchen also nicht wirklich Query.

Aber Sie brauchen Path für den item_id-Pfad-Parameter. Und Sie möchten aus irgendeinem Grund nicht Annotated verwenden.

Python wird sich beschweren, wenn Sie einen Parameter mit Defaultwert vor einen Parameter ohne Defaultwert setzen.

Aber Sie können die Reihenfolge der Parameter ändern, den Query-Parameter ohne Defaultwert zuerst.

Für FastAPI ist es nicht wichtig. Es erkennt die Parameter anhand ihres Namens, ihrer Typen, und ihrer Defaultwerte (Query, Path, usw.). Es kümmert sich nicht um die Reihenfolge.

Sie können Ihre Funktion also so deklarieren:

Tipp

Bevorzugen Sie die Annotated-Version, falls möglich.

from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(q: str, item_id: int = Path(title="The ID of the item to get")):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

Aber bedenken Sie, dass Sie dieses Problem nicht haben, wenn Sie Annotated verwenden, da Sie nicht die Funktions-Parameter-Defaultwerte für Query() oder Path() verwenden.

from typing import Annotated

from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    q: str, item_id: Annotated[int, Path(title="The ID of the item to get")]
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results
🤓 Other versions and variants
from fastapi import FastAPI, Path
from typing_extensions import Annotated

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    q: str, item_id: Annotated[int, Path(title="The ID of the item to get")]
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(q: str, item_id: int = Path(title="The ID of the item to get")):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

Sortieren Sie die Parameter wie Sie möchten: Tricks

Tipp

Wenn Sie Annotated verwenden, ist das folgende nicht so wichtig / nicht notwendig.

Hier ein kleiner Trick, der nützlich sein kann, aber Sie werden ihn nicht oft brauchen.

Wenn Sie eines der folgenden Dinge tun möchten:

  • den q-Parameter ohne Query oder irgendeinem Defaultwert deklarieren
  • den Pfad-Parameter item_id mittels Path deklarieren
  • die Parameter in einer unterschiedlichen Reihenfolge haben
  • Annotated nicht verwenden

... dann hat Python eine kleine Spezial-Syntax für Sie.

Übergeben Sie der Funktion * als ersten Parameter.

Python macht nichts mit diesem *, aber es wird wissen, dass alle folgenden Parameter als Keyword-Argumente (Schlüssel-Wert-Paare), auch bekannt als kwargs, verwendet werden. Selbst wenn diese keinen Defaultwert haben.

from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(*, item_id: int = Path(title="The ID of the item to get"), q: str):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results
🤓 Other versions and variants
from typing import Annotated

from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get")], q: str
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results
from fastapi import FastAPI, Path
from typing_extensions import Annotated

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get")], q: str
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

Besser mit Annotated

Bedenken Sie, dass Sie, wenn Sie Annotated verwenden, dieses Problem nicht haben, weil Sie keine Defaultwerte für Ihre Funktionsparameter haben. Sie müssen daher wahrscheinlich auch nicht * verwenden.

from typing import Annotated

from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get")], q: str
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results
🤓 Other versions and variants
from fastapi import FastAPI, Path
from typing_extensions import Annotated

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get")], q: str
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(*, item_id: int = Path(title="The ID of the item to get"), q: str):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

Validierung von Zahlen: Größer oder gleich

Mit Query und Path (und anderen, die Sie später kennenlernen), können Sie Zahlenbeschränkungen deklarieren.

Hier, mit ge=1, wird festgelegt, dass item_id eine Ganzzahl benötigt, die größer oder gleich 1 ist (greater than or equal).

from typing import Annotated

from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get", ge=1)], q: str
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results
🤓 Other versions and variants
from fastapi import FastAPI, Path
from typing_extensions import Annotated

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get", ge=1)], q: str
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    *, item_id: int = Path(title="The ID of the item to get", ge=1), q: str
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

Validierung von Zahlen: Größer und kleiner oder gleich

Das Gleiche trifft zu auf:

  • gt: greater than – größer als
  • le: less than or equal – kleiner oder gleich
from typing import Annotated

from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get", gt=0, le=1000)],
    q: str,
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results
🤓 Other versions and variants
from fastapi import FastAPI, Path
from typing_extensions import Annotated

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get", gt=0, le=1000)],
    q: str,
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Path

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    *,
    item_id: int = Path(title="The ID of the item to get", gt=0, le=1000),
    q: str,
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    return results

Validierung von Zahlen: Floats, größer und kleiner

Zahlenvalidierung funktioniert auch für float-Werte.

Hier wird es wichtig, in der Lage zu sein, gt zu deklarieren, und nicht nur ge, da Sie hiermit bestimmen können, dass ein Wert, zum Beispiel, größer als 0 sein muss, obwohl er kleiner als 1 ist.

0.5 wäre also ein gültiger Wert, aber nicht 0.0 oder 0.

Das gleiche gilt für lt.

from typing import Annotated

from fastapi import FastAPI, Path, Query

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    *,
    item_id: Annotated[int, Path(title="The ID of the item to get", ge=0, le=1000)],
    q: str,
    size: Annotated[float, Query(gt=0, lt=10.5)],
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    if size:
        results.update({"size": size})
    return results
🤓 Other versions and variants
from fastapi import FastAPI, Path, Query
from typing_extensions import Annotated

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    *,
    item_id: Annotated[int, Path(title="The ID of the item to get", ge=0, le=1000)],
    q: str,
    size: Annotated[float, Query(gt=0, lt=10.5)],
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    if size:
        results.update({"size": size})
    return results

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Path, Query

app = FastAPI()


@app.get("/items/{item_id}")
async def read_items(
    *,
    item_id: int = Path(title="The ID of the item to get", ge=0, le=1000),
    q: str,
    size: float = Query(gt=0, lt=10.5),
):
    results = {"item_id": item_id}
    if q:
        results.update({"q": q})
    if size:
        results.update({"size": size})
    return results

Zusammenfassung

Mit Query und Path (und anderen, die Sie noch nicht gesehen haben) können Sie Metadaten und Stringvalidierungen deklarieren, so wie in Query-Parameter und Stringvalidierungen beschrieben.

Und Sie können auch Validierungen für Zahlen deklarieren:

  • gt: greater than – größer als
  • ge: greater than or equal – größer oder gleich
  • lt: less than – kleiner als
  • le: less than or equal – kleiner oder gleich

Info

Query, Path, und andere Klassen, die Sie später kennenlernen, sind Unterklassen einer allgemeinen Param-Klasse.

Sie alle teilen die gleichen Parameter für zusätzliche Validierung und Metadaten, die Sie gesehen haben.

Technische Details

Query, Path und andere, die Sie von fastapi importieren, sind tatsächlich Funktionen.

Die, wenn sie aufgerufen werden, Instanzen der Klassen mit demselben Namen zurückgeben.

Sie importieren also Query, welches eine Funktion ist. Aber wenn Sie es aufrufen, gibt es eine Instanz der Klasse zurück, die auch Query genannt wird.

Diese Funktionen existieren (statt die Klassen direkt zu verwenden), damit Ihr Editor keine Fehlermeldungen über ihre Typen ausgibt.

Auf diese Weise können Sie Ihren Editor und Ihre Programmier-Tools verwenden, ohne besondere Einstellungen vornehmen zu müssen, um diese Fehlermeldungen stummzuschalten.