How to disallow empty parameters in FastAPI?

10.1k views Asked by At

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

There are 3 answers

0
kozhushman On BEST ANSWER

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

1
Yagiz Degirmenci On

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
0
JPG On

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\"]}"