I have the following code
from pydantic import BaseModel
class Product(BaseModel):
name: str
tags: list[str] # Accepted tags: "mean", "std", "extra_<float with 1 decimal point>".
The tags
is a list
of str
. But it only accepts certain words.
mean
and std
.extra_
and be followed by a float with 1 decimal point. For example extra_1.0
, extra_2.5
. But extra_3.14
is not allowed.Can you please show me how to implement it?
Thanks.
EDIT: Thanks to Yurii Motov
1st solution
You can use Union, Literal, Annotated and StringConstraints
(not constr, due to: Pydantic docs, constr will be deleted in 3.0 version)
from typing_extensions import Annotated, Union, Literal
from pydantic import BaseModel, StringConstraints
class Product(BaseModel):
name: str
tags: list[Union[Literal['mean', 'std'],
Annotated[str, StringConstraints(pattern=r'exp\_[0-9]\.[0-9]')]]]
if input string doesn't match expectations this error will raise:
Input should be 'mean' or 'std' [type=literal_error,
input_value='template', input_type=str]...
String should match pattern 'exp\_[0-9]\.[0-9]'
[type=string_pattern_mismatch, input_value='template', input_type=str]
or a similar one
2nd solution
Also you can use Annotated and Function validation (docs: Pydantic docs), see here:
My simple example:
def handler(s: str):
#write the desired handler
if(not s == 'template'):
raise TypeError('Not valid string')
return s
MyStr = Annotated[str, BeforeValidator(handler)]
class Product(BaseModel):
name: str
tags: list[MyStr]
# this will raise TypeError, because of int input
# product = Product(name = 'name', tags = [1])
# this will also raise TypeError, that inside handler
# product = Product(name = 'name', tags = ['1','template'])
# this is totally fine
product = Product(name = 'name', tags = ['template','template'])
but you should rewrite handler