JeanDevFR
JeanDevFR

Reputation: 91

Fastapi Pydantic optional field

Currently, I'm learning Python and Fastapi and I can't figure out what typing.Optional is for.

class Post(BaseModel):
    # default value
    rating: int = None
    # typing.Optional
    rating: Optional[int] = None

Both work. I don't understand what's the difference.

Upvotes: 7

Views: 28655

Answers (1)

Paul P
Paul P

Reputation: 3897

From the documentation (see typing.Optional):

Optional[x] is simply short hand for Union[x, None]

In Pydantic this means, specifying the field value becomes optional. In other words, it's not necessary to pass in the field and value when initialising the model, and the value will default to None (this is slightly different to optional arguments in function calls as described here).

It's also not necessary to explicitly specify None as the default.

It appears to be mostly syntactic sugar in this case but it helps to make the model more readable. In more advanced cases, it may be necessary to require a field to be explicitly passed into the model, even though the value could be None, as suggested in the section on Required Optional Fields, in which case the distinction becomes necessary.

It always depends on the use case but it's not unusual to use a default value of the same type, or make the field required.

Here's a more common scenario for this:

from pydantic import BaseModel
from typing import Optional

class Post(BaseModel):
    # rating is required and must be an integer.
    rating: int

    # counter is not required and will default to 1 if nothing is passed.
    counter: int = 1

    # comment is optional and will be coerced into a str.
    comment: Optional[str]
# This will work:
post = Post(rating=10)
repr(post)
# 'Post(rating=10, counter=1, comment=None)'

# This will work as well:
post = Post(rating=10, comment="some text")
repr(post)
# "Post(rating=10, counter=1, comment='some text')"

# But this won't work:
post = Post(comment="some text")

# ...
# ValidationError: 1 validation error for Post
# rating
#   field required (type=value_error.missing)

# And this won't work either:
post = Post(rating=10, counter=None)

# ...
# ValidationError: 1 validation error for Post1
# counter
#   none is not an allowed value (type=type_error.none.not_allowed)

Upvotes: 8

Related Questions