from pydantic import BaseModel, PositiveInt
29 Pydantic
29.1 Pydantic Example
https://docs.pydantic.dev/2.9/#pydantic-examples
29.1.1 Base
from datetime import datetime
class User(BaseModel):
id: int
str = 'John Doe'
name: | None
signup_ts: datetime dict[str, PositiveInt] tastes:
= {
external_data 'id': 123,
'signup_ts': '2019-06-01 12:22',
'tastes': {
'wine': 9,
b'cheese': 7,
'cabbage': '1',
}, }
= User(**external_data)
user user
User(id=123, name='John Doe', signup_ts=datetime.datetime(2019, 6, 1, 12, 22), tastes={'wine': 9, 'cheese': 7, 'cabbage': 1})
# access fields as attributes of the model.
id user.
123
29.1.2 Serialization
# convert the model to a dictionary
= user.model_dump()
user_dict user_dict
{'id': 321,
'name': 'John Doe',
'signup_ts': datetime.datetime(2019, 6, 1, 12, 22),
'tastes': {'wine': 9, 'cheese': 7, 'cabbage': 1}}
# Include
print(user.model_dump(include={"id", "name"}))
# Exclude
print(user.model_dump(exclude={"id", "name"}))
{'id': 321, 'name': 'John Doe'}
{'signup_ts': datetime.datetime(2019, 6, 1, 12, 22), 'tastes': {'wine': 9, 'cheese': 7, 'cabbage': 1}}
import json
# convert the model to a JSON
= user.model_dump_json()
user_json_str json.loads(user_json_str)
{'id': 321,
'name': 'John Doe',
'signup_ts': '2019-06-01T12:22:00',
'tastes': {'wine': 9, 'cheese': 7, 'cabbage': 1}}
29.1.3 Validation Fail
If validation fails, Pydantic will raise an error with a breakdown of what was wrong
from pydantic import BaseModel, PositiveInt, ValidationError
= {'id': 'not an int', 'tastes': {}}
external_data
try:
**external_data)
User(except ValidationError as e:
print(e.errors())
[{'type': 'int_parsing', 'loc': ('id',), 'msg': 'Input should be a valid integer, unable to parse string as an integer', 'input': 'not an int', 'url': 'https://errors.pydantic.dev/2.9/v/int_parsing'}, {'type': 'missing', 'loc': ('signup_ts',), 'msg': 'Field required', 'input': {'id': 'not an int', 'tastes': {}}, 'url': 'https://errors.pydantic.dev/2.9/v/missing'}]
29.1.4 Mutable Model
By default, models are mutable and field values can be changed through attribute assignment:
id = 321
user.assert user.id == 321
29.2 Field
The Field
function is used to customize and add metadata to fields of models.
29.2.1 Default values
from pydantic import BaseModel, Field
class User(BaseModel):
str = Field(default='John Doe')
name:
= User()
user user
User(name='John Doe')
You can also use default_factory
to define a callable that will be called to generate a default value.
from uuid import uuid4
from pydantic import BaseModel, Field
class User(BaseModel):
id: str = Field(default_factory=lambda: uuid4().hex)
29.3 JSON Schema
29.3.1 Generating JSON Schema
import json
from enum import Enum
from typing import Annotated
from pydantic import BaseModel, Field
from pydantic.config import ConfigDict
class FooBar(BaseModel):
int
count: float | None = None
size:
class Gender(str, Enum):
= 'male'
male = 'female'
female = 'other'
other = 'not_given'
not_given
class MainModel(BaseModel):
"""
This is the description of the main model
"""
= ConfigDict(title='Main')
model_config
foo_bar: FooBar| None, Field(alias='Gender')] = None
gender: Annotated[Gender int = Field(
snap: 42,
='The Snap',
title='this is the value of snap',
description=30,
gt=50,
lt
)
= MainModel.model_json_schema()
main_model_schema # JSON String
print(json.dumps(main_model_schema, indent=2))
{
"$defs": {
"FooBar": {
"properties": {
"count": {
"title": "Count",
"type": "integer"
},
"size": {
"anyOf": [
{
"type": "number"
},
{
"type": "null"
}
],
"default": null,
"title": "Size"
}
},
"required": [
"count"
],
"title": "FooBar",
"type": "object"
},
"Gender": {
"enum": [
"male",
"female",
"other",
"not_given"
],
"title": "Gender",
"type": "string"
}
},
"description": "This is the description of the main model",
"properties": {
"foo_bar": {
"$ref": "#/$defs/FooBar"
},
"Gender": {
"anyOf": [
{
"$ref": "#/$defs/Gender"
},
{
"type": "null"
}
],
"default": null
},
"snap": {
"default": 42,
"description": "this is the value of snap",
"exclusiveMaximum": 50,
"exclusiveMinimum": 30,
"title": "The Snap",
"type": "integer"
}
},
"required": [
"foo_bar"
],
"title": "Main",
"type": "object"
}
29.3.2 Type Adapter
from typing import List
from pydantic import TypeAdapter
= TypeAdapter(List[int])
adapter print(adapter.json_schema())
{'items': {'type': 'integer'}, 'type': 'array'}