5

I have FastAPI function like this:

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

I want "ids" field as required and pass there values like ["1", "2"]. If I pass a valid list it working fine. But if I pass empty list - [], this is also will be valid param and I dont want that. I can write function that checks it myself pretty easy, but I feel from my expirience with this wonderful framework that FastAPI have it covered already and I just dont know how.

3 Answers 3

5

Method 1: use field validator -- (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

Method 2: Use min_items argument of Field--(Pydantic Doc) class

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

example cURL request:

curl -X POST "http://0.0.0.0:8000/test/" -H  "accept: application/json" -H  "Content-Type: application/json" -d "{\"ids\":[\"string\"]}"
Sign up to request clarification or add additional context in comments.

Comments

3

I finally found a solution (after about half-hour of research) - in pydantic you may pass min_items to indicate minimum amount of items in passing list.
More on options here: https://pydantic-docs.helpmanual.io/usage/schema/#field-customisation

So in the end, pydantic + FastAPI for my case will be like this:

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

In this case we gain functionality of pydantic, but without need of pydantic BaseModel class

Comments

2

I 'd prefer a validator since most endpoints won't be simple like this.

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

1 Comment

what is cls in this scenario?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.