Hi!
Is pydantic support empty values? I didn't see anything in docs about empty or blank values. I have seen that I could write custom validator and return None when string is empty but maybe there is easier solution. Or if there is option to support empty values in future?
from datetime import date
from typing import Optional
from pydantic import BaseModel
class CustomModel(BaseModel):
custom_int: Optional[int] = None
custom_date: Optional[date] = None
CustomModel(**{'custom_int': '', 'custom_date': ''})
ValidationError: 4 validation errors
custom_int
value is not a valid integer (type=type_error.integer)
custom_int
value is not none (type=type_error.none.allowed)
custom_date
invalid date format (type=type_error.date)
custom_date
value is not none (type=type_error.none.allowed)
There's no such option. None is supported but not empty strings.
You'll need to use custom validators.
Does the use of custom validators significantly affect performance? Will lib support empty string in future?
Custom validators should have a negligible on performance.
I've no plans to add specific support for empty strings to pydantic.
Just as a note or "workaround" @krzysieqq:
Although it is not really "empty string values accepted as date", you can define a field as a Union of other types ("union" means "any of these types"). And you can then use Pydantic's constr() to create a type str with constraints, making it only accept empty strings.
So, this code:
import json
from datetime import date
from typing import Optional, Union
from pydantic import BaseModel, constr
class CustomModel(BaseModel):
custom_int: Optional[Union[int, constr(max_length=0)]] = None
custom_date: Optional[Union[date, constr(max_length=0)]] = None
print(CustomModel(**{'custom_int': '', 'custom_date': ''}).json())
print(CustomModel(**{'custom_int': 3, 'custom_date': '2019-01-20'}).json())
print(CustomModel(**{'custom_int': 'str but not empty', 'custom_date': 'str but not empty'}).json())
would print:
{"custom_int": "", "custom_date": ""}
{"custom_int": 3, "custom_date": "2019-01-20"}
Traceback (most recent call last):
File "sand.py", line 14, in <module>
print(CustomModel(**{'custom_int': 'str but not empty', 'custom_date': 'str but not empty'}).json())
File "/home/user/code/pydantic/pydantic/main.py", line 142, in __init__
self.__setstate__(self._process_values(data))
File "/home/user/code/pydantic/pydantic/main.py", line 312, in _process_values
return validate_model(self, input_data)
File "/home/user/code/pydantic/pydantic/main.py", line 474, in validate_model
raise ValidationError(errors)
pydantic.error_wrappers.ValidationError: 6 validation errors
custom_int
value is not a valid integer (type=type_error.integer)
custom_int
ensure this value has at most 0 characters (type=value_error.any_str.max_length; limit_value=0)
custom_int
value is not none (type=type_error.none.allowed)
custom_date
invalid date format (type=type_error.date)
custom_date
ensure this value has at most 0 characters (type=value_error.any_str.max_length; limit_value=0)
custom_date
value is not none (type=type_error.none.allowed)
Note that the first two lines (with "valid data" for your use case) are taken as valid.
So, an empty string is actually accepted. And it shows an error only when the value passed is not of the first type (int, date) or is a non-empty string.
Thx for help and workaround :)!
Most helpful comment
Just as a note or "workaround" @krzysieqq:
Although it is not really "empty string values accepted as date", you can define a field as a
Unionof other types ("union" means "any of these types"). And you can then use Pydantic'sconstr()to create a typestrwith constraints, making it only accept empty strings.So, this code:
would print:
Note that the first two lines (with "valid data" for your use case) are taken as valid.
So, an empty string is actually accepted. And it shows an error only when the value passed is not of the first type (
int,date) or is a non-empty string.