Change default Pydantic to SQLAlchemy mappings¶
In most cases, you do not need to know how SQLAlchemy transforms the Python types to the type suitable for storing data in the database, and you can use the default mapping.
But in some cases you may need to have possibility to change default mapping provided by SQLmodel. For example to use mssql dialect with some UTF-8 data you should use NVARCHAR field (sa.Unicode)
Now changing default mapping is simple to use - see example bellow:
import sqlmodel.main
import sqlalchemy as sa
from sqlmodel import Field, SQLModel
from typing import Optional
sqlmodel.main.sa_types_map[str] = lambda type_, meta, annotation: sa.Unicode(
length=getattr(meta, "max_length", None)
)
class Hero(SQLModel, table=True):
id: int = Field(default=None, primary_key=True)
name: str = Field(max_length=255)
history: Optional[str]
assert isinstance(Hero.name.type, sa.Unicode)
Some details¶
Let's get little deeper to process of mapping. At the sqlmodel.main module defined the sa_types_map dictionary,
which uses the Python types as keys, and the sqlalchemy type or callable that takes the input of 3 parameters and
returns the sqlalchemy type as values.
Callable format present bellow:
def map_python_type_to_sa_type(type_: "PythonType", meta: "PydanticMeta", annotation: "FieldAnnotatedType"):
return sqlalchemyType(length=getattr(meta, "max_length", None))
type_- used to pass python type, provided by pydantic annotation, cleared from Union/Optional and other wrappers. Can be passed to sa.Enum type to properly store enumerated data.meta- pydantic metadata used to store field params e.g. length of str field or precision of decimal fieldannotation- original annotation given by pydantic. Used to providetypeparameter for PydanticJSONType
Current mapping¶
| Python type | SqlAlchemy type |
|---|---|
| Enum | lambda type_, meta, annotation: sa_Enum(type_) |
| str | lambda type_, meta, annotation: AutoString(length=getattr(meta, "max_length", None)) |
| float | Float |
| bool | Boolean |
| int | Integer |
| datetime | DateTime |
| date | Date |
| timedelta | Interval |
| time | Time |
| bytes | LargeBinary |
| Decimal | lambda type_, meta, annotation: Numeric(precision=getattr(meta, "max_digits", None),scale=getattr(meta, "decimal_places", None)) |
| ipaddress.IPv4Address | AutoString |
| ipaddress.IPv4Network | AutoString |
| ipaddress.IPv6Address | AutoString |
| ipaddress.IPv6Network | AutoString |
| Path | AutoString |
| uuid.UUID | Uuid |
| BaseModel | lambda type_, meta, annotation: PydanticJSONType(type=annotation) |