«Если рабочий хочет хорошо выполнять свою работу, он должен сначала заточить свои инструменты» — Конфуций, «Аналитики Конфуция. Лу Лингун»
титульная страница > программирование > FastAPI: как использовать Pydantic для объявления параметров запроса

FastAPI: как использовать Pydantic для объявления параметров запроса

Опубликовано 19 ноября 2024 г.
Просматривать:378

Около трёх недель назад появилась одна из самых ожидаемых функций FastAPI. По крайней мере, когда мы говорим о моделях Pydantic FastAPI.

Да, я говорю о возможности использовать модели Pydantic для сопоставления параметров вашего запроса.

Итак, в этом посте я постараюсь показать вам все, что вы ? может и? не могу поделать с этой темой ?:

? Сопоставление параметров запроса

Первое, что вам нужно сделать, чтобы начать сопоставление параметров запроса с помощью Pydantic, — это убедиться, что вы используете FastAPI версии 0.115.0.

После этого вы всегда можете перейти к документации FastAPI, чтобы проверить, что уже доступно. Себастьян и члены команды очень, очень хорошо работают над обновлением и информативностью документации ✨.

? Немного истории

Давайте начнем с нескольких примеров того, как мы использовали для сопоставления параметров запроса в FastAPI. ?

Самый простой способ сделать это:

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def search(
    limit: int | None = 10,
    skip: int | None = 1,
    filter: str | None = None
):
    return {
        "limit": limit,
        "skip": skip,
        "filter": filter
    }

А теперь вы можете просто позвонить:

GET http://localhost:8000/?limit=42&skip=12&filter=banana

Но если бы мы определили, что эти параметры запроса будут использоваться в других маршрутах, мы бы изолировали их с помощью чего-то вроде:

from typing import Any
from fastapi import Depends, FastAPI, Query

app = FastAPI()

async def pagination_query_string(
    limit: int | None = Query(10, ge=5, le=100),
    skip: int | None = Query(1, ge=1),
    filter: str | None = Query(None)
) -> dict[str, Any]:
    return {
        "limit": limit,
        "skip": skip,
        "filter": filter
    }

@app.get("/")
async def search(q: dict[str, Any] = Depends(pagination_query_string)):
    return q

Или, поскольку мы используем Pydantic для отображения наших моделей, после небольшого рефакторинга мы получим:

from fastapi import Depends, FastAPI, Query
from pydantic import BaseModel

app = FastAPI()

class PaginationQueryString(BaseModel):
    limit: int | None = 10
    skip: int | None = 1
    filter: str | None = None

async def pagination_query_string(
    limit: int | None = Query(10, ge=5, le=100),
    skip: int | None = Query(1, ge=1),
    filter: str | None = Query(None)
) -> PaginationQueryString:
    return PaginationQueryString(
        limit=limit,
        skip=skip,
        filter=filter
    )

@app.get("/")
async def search(q: PaginationQueryString = Depends(pagination_query_string)):
    return q

⌨️ Использование Pydantic для сопоставления строк запроса

FastAPI: How to use Pydantic to declare Query Parameters

Теперь, если мы хотим получить строку запроса, нам не нужно создавать функцию, а затем добавлять ее в качестве зависимости. Мы можем просто сообщить FastAPI, что нам нужен объект типа PaginationQueryString и что это строка запроса:

from typing import Annotated
from fastapi import FastAPI, Query
from pydantic import BaseModel

app = FastAPI()

class PaginationQueryString(BaseModel):
    limit: int | None = 10
    skip: int | None = 1
    filter: str | None = None

@app.get("/")
async def search(q: Annotated[PaginationQueryString, Query()]):
    return q

Легко, правда? ?

⚠️Какие ограничения?

По крайней мере, в версии 0.115.0 это не очень хорошо работает с вложенными моделями.

Давайте попробуем что-нибудь вроде:

from typing import Annotated
from fastapi import FastAPI, Query
from pydantic import BaseModel

app = FastAPI()

class Filter(BaseModel):
    name: str | None = None
    age: int | None = None
    nickname: str | None = None

class PaginationQueryString(BaseModel):
    limit: int | None = 10
    skip: int | None = 1
    filter: Filter | None = None

@app.get("/")
async def search(q: Annotated[PaginationQueryString, Query()]):
    return q

Если мы назовем это как раньше:

GET http://localhost:8000/?limit=42&skip=12&filter=chocolate

Мы получим сообщение об ошибке, сообщающее, что фильтр является объектом:

{
    "detail": [
        {
            "type": "model_attributes_type",
            "loc": [
                "query",
                "filter"
            ],
            "msg": "Input should be a valid dictionary or object to extract fields from",
            "input": "chocolate"
        }
    ]
}

По крайней мере сейчас, это абсолютно правильно! Мы изменили наш фильтр, чтобы он стал моделью Pydantic, а не строкой. Но если мы попытаемся преобразовать его в словарь:

http://localhost:8000/?limit=42&skip=12&filter={"name": "Rafael", "age": 38, "nickname": "ceb10n"}

FastAPI сообщит нам, что фильтр должен быть действительным словарем ?:

{
    "detail": [
        {
            "type": "model_attributes_type",
            "loc": [
                "query",
                "filter"
            ],
            "msg": "Input should be a valid dictionary or object to extract fields from",
            "input": "{\"name\": \"Rafael\", \"age\": 38, \"nickname\": \"ceb10n\"}"
        }
    ]
}

Это происходит потому, что FastAPI будет полагаться на QueryParams Starlette, который передает FastAPI строку, а не словарь. И по крайней мере в версии 0.115.0 это выдаст ошибку.

⁉️ Итак, когда я использую модели Pydantic с параметрами запроса?

Все очень просто:

✅ У вас есть простые строки запроса, для которых не нужны сложные вложенные объекты? Используйте это! ?

❌ Вы создали сложную вложенную строку запроса? Еще не пользуетесь? (И, возможно, вам стоит попытаться переосмыслить строки запроса. ? Чем проще, тем лучше?)

Заявление о выпуске Эта статья воспроизведена по адресу: https://dev.to/ceb10n/fastapi-how-to-use-pydantic-to-declare-query-parameters-25bd?1 Если есть какие-либо нарушения, пожалуйста, свяжитесь с [email protected] удалить его
Последний учебник Более>

Изучайте китайский

Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.

Copyright© 2022 湘ICP备2022001581号-3