I have some FastAPI application:
from typing import Annotated
import uvicorn
from fastapi import FastAPI, Query
from pydantic import constr
app = FastAPI()
@app.get("search")
async def search(
partner_ids: Annotated[
constr(pattern="((^|[,])[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12})+"),
Query(),
] = "ca930bc7-f4cf-4b10-9c6f-7db13b6ab4f0",
):
pass
if __name__ == "__main__":
uvicorn.run("uuid_list:app", reload=True, port=8004)
The problem with it is validation of partner_ids
does not work:
At the same time regex101 finds uuid:
What's wrong with FastAPI?
Upd. The regex is for comma separated list of uuids.
As @MatsLindh mentioned in the comment you can just use List[type]
. In your case it will be:
@app.get("search")
async def search(
partner_ids: Annotated[List[UUID], Query(...)]
):
pass
It won't be a comma separated but at least it work out of a box.
In your example it seems that you have in issue in regex. Try to set uuid pattern like this:
UUIDPattern = constr(
regex=r"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})(,[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})*$"
)
@app.get("/search")
async def search(
partner_ids: Annotated[UUIDListPattern], Query()],
):
pass
There is a third option using a schema:
# Pydantic model for validating the input schema
class PartnerIDsSchema(BaseModel):
partner_ids: str
@validator('partner_ids')
def check_uuids(cls, v):
uuids = v.split(",")
for uuid_str in uuids:
try:
UUID(uuid_str.strip())
except ValueError:
raise ValueError(f"Invalid UUID found: {uuid_str}")
return v
@app.get("/search")
async def search(
partner_ids: PartnerIDsSchema = Query(...)
):
pass
But you will need to convert then in actual uuids in the method itself because they will be passed as a single string.