Easiest: Use typing.Literal
Literal
is a good option when you can hardcode your values:
class Input(BaseModel):
option: Litera["foo", "bar"]
It will fail if your list of strings are dynamic:
allowed_values = ["foo", "bar"]
class Input(BaseModel):
option: Literal[allowed_values]
Alt: Use Validator
Assuming it is not possible to transcode into regex (say you have objects, not only strings), you would then want to use a field validator:
allowed_values = ["foo", "bar"]
class Input(BaseModel):
option: str
@field_validator("option")
def validate_option(cls, v):
assert v in allowed_values
return v
Best: Reusable Field with Annotated Validator
Let's say this field (and validator) are going to be reused in your codebase. A better approach would be to create a "custom field type" with an annotated validator, as such:
from typing import Annotated
from pydantic import BaseModel, AfterValidator
allowed_values = ["foo", "bar"]
def option_in_allowed_values(v):
"""Ensures option is allowed"""
assert v in allowed_values
return v
custom_option = Annotated[str, AfterValidator(option_in_allowed_values)]
class Input(BaseModel):
option: custom_option