0

Following the Pydantic custom data types instructions, I've created a type which attempts to get strings from a single comma-separated string like:

"foo,bar,baz" -> ["foo", "bar", "baz"]

It works fine:

class CommaSeparatedString(str):
    @classmethod
    def __get_validators__(cls):
        yield cls.split_on_comma

    @classmethod
    def split_on_comma(cls, v: str | None):
        if not v:
            return None

        if not isinstance(v, str):
            raise TypeError("String required")

        return [item.strip() for item in v.split(",")]


@app.get("/")
def applications_index(
    strings: CommaSeparatedString | None,
):
    print(strings)

But FastAPI doesn't honour the optional nature of the strings param.

It complains about missing fields when I make a request without strings in the querystring:

{'detail': [{'loc': ['query', 'strings'], 'msg': 'field required', 'type': 'value_error.missing'}]
Chris
  • 18,724
  • 6
  • 46
  • 80
LondonRob
  • 73,083
  • 37
  • 144
  • 201
  • Please have a look at the "Note" section in the link provided above, as well as at the "About Optional Parameters" section of [this answer](https://stackoverflow.com/a/73261442/17865804). In short, "the most important part to make a parameter optional is the part: `= None`". Since you are dealing with arbitrary query parameters, you may find [this](https://stackoverflow.com/a/70840850/17865804) and [this](https://stackoverflow.com/a/73831142/17865804) helpful as well. – Chris May 01 '23 at 17:38

1 Answers1

1

I believe You need to add default value, so Your code would look like that:

class CommaSeparatedString(str):
    @classmethod
    def __get_validators__(cls):
        yield cls.split_on_comma

    @classmethod
    def split_on_comma(cls, v: str | None):
        if not v:
            return None

        if not isinstance(v, str):
            raise TypeError("String required")

        return [item.strip() for item in v.split(",")]


@app.get("/")
def applications_index(
    strings: CommaSeparatedString | None = None,
):
    print(strings)
M.O.
  • 1,712
  • 1
  • 6
  • 18
Matmozaur
  • 283
  • 2
  • 6
  • Thanks! This is a real facepalm moment for me. Yes, I should have set `= None` to make it work. Thanks for pointing this out. – LondonRob May 02 '23 at 09:26