Как запретить пустые параметры в FastAPI?

У меня есть функция FastAPI, подобная этой:

@router.post("/test/")
async def test(ids: List[str] = Body(..., )):
    # some logic

Мне нужно поле ids по мере необходимости и передавать туда значения, такие как [1, 2]. Если я передам действительный список, он работает нормально. Но если я передам пустой список - [], это также будет допустимым параметром, а я этого не хочу. Я могу написать функцию, которая проверяет это самостоятельно, довольно легко, но из моего опыта работы с этой замечательной структурой я чувствую, что FastAPI уже покрыл ее, и я просто не знаю, как это сделать.


person kozhushman    schedule 28.09.2020    source источник


Ответы (3)


Я бы предпочел валидатор, так как большинство конечных точек выиграли не будь таким простым.

from pydantic import validator, BaseModel
from fastapi import FastAPI, Body
from typing import List

app = FastAPI()


class User(BaseModel):
    ids: List[str]

    @validator("ids", pre=True, always=True)
    def check_ids(cls, ids):
        assert len(ids) > 0, "ID's cannot be empty."
        return ids


@app.post("/test")
async def get_ids(user: User = Body(...)):
    return user
person Yagiz Degirmenci    schedule 28.09.2020

Наконец-то я нашел решение (примерно через полчаса исследований) — в pydantic вы можете передать min_items, чтобы указать минимальное количество элементов в списке прохождения.
Подробнее о вариантах здесь: https://pydantic-docs.helpmanual.io/usage/schema/#field-customisation

Так что в итоге pydantic + FastAPI для моего случая будет таким:

@router.post("/test/")
async def test(ids: List[str] = Body(..., min_items=1)):
    # some logic

В этом случае мы получаем функциональность pydantic, но без необходимости использования класса BaseModel pydantic.

person kozhushman    schedule 28.09.2020

Способ 1: используйте поле валидатор -- (Pydantic Doc)

from pydantic import BaseModel, validator


class MyModel(BaseModel):
    ids: List[str] = []

    @validator('ids', pre=True, always=True)
    def validate_ids_length(cls, value):
        if len(value) == 0:
            raise ValueError("empty list not allowed")
        return value


@demo_app.post("/test/")
async def test(data: MyModel = Body(...)):
    return data

Способ 2. Используйте аргумент min_items для Field--(Pydantic Doc) класс

from pydantic import BaseModel, Field


class MyModel(BaseModel):
    ids: List[str] = Field(..., min_items=1)


@demo_app.post("/test/")
async def test(data: MyModel = Body(...)):
    return data

пример cURL-запроса:

curl -X POST "http://0.0.0.0:8000/test/" -H  "accept: application/json" -H  "Content-Type: application/json" -d "{\"ids\":[\"string\"]}"
person JPG    schedule 28.09.2020