I have a very simple FastAPI GET
endpoint. It does not accept any request body - it only accepts a single, mandatory GET
parameter. For example:
/v1/app/end?foo=abcdef1234567890
This foo
parameter absolutely must conform to some regex. I've simplified the regex for the purposes of this question, but it's nothing crazy.
This was easy enough to do, and in fact, I had it working in Pydantic 1.9:
# Works perfectly with Pydantic v1.9
from pydantic import constr
MY_REGEX = r"^[a-z0-9]{16}$"
@router.get(
"/v1/app/end",
response_model=src.schemas.foo.Bar,
)
def get_with_parameter(
foo: constr(regex=MY_REGEX),
) -> src.schemas.foo.Bar:
Now, moving to Pydantic 2.5, I can no longer do this. Note that I have renamed regex
to pattern
, but it should still do the same thing.
# Validation is completely ignored!
def get_with_parameter(
foo: constr(pattern=MY_REGEX),
) -> src.schemas.foo.Bar:
Following the suggestions in the official documentation and source code does not work either:
# Validation is completely ignored!
from typing_extensions import Annotated
from pydantic import StringConstraints
def get_with_parameter(
foo: Annotated[str, StringConstraints(pattern=MY_REGEX)],
) -> src.schemas.foo.Bar:
I found that I can make it work again, but only if I make it Optional, Final, or some other weird type, which I do not want to do:
from typing import Optional, Final
# Validation works, but is now Optional
def get_with_parameter(
foo: Optional[constr(pattern=MY_REGEX)],
) -> src.schemas.foo.Bar:
# Validation works, but is now Final
def get_with_parameter(
foo: Final[constr(pattern=MY_REGEX)],
) -> src.schemas.foo.Bar:
--
How can I get this to work like it used to?
I found a fix, which was to use the Query
type from FastAPI
from typing import Annotated
from fastapi import Query
@router.get(
"/v1/app/end",
response_model=src.schemas.foo.Bar,
)
def get_with_parameter(
foo: Annotated[str, Query(pattern=MY_REGEX)]),
) -> src.schemas.foo.Bar: