Skip to content

基于pydantic 2.XX迁移到0.20.0

版本 0.20.0 提供了对 pydantic v2.XX 的支持,为开发人员提供了显着的速度提升(验证和序列化是用 rust 编写的)和更干净的 api,同时它放弃了对 pydantic v.1.XX 的支持 ormar 中有更改与 pydantic 中所做的更改相对应的界面。

重大变化

迁移到版本 >= 0.20.0 需要进行多项更改才能正常工作。

奥玛 型号配置

现在,每个 ormar 模型都需要一个 ormar_config 参数,该参数是 OrmarConfig 类的实例,而不是定义 Meta 类。请注意,该属性必须命名为 ormar_config 并且是 config 类的实例。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import databases
import ormar
import sqlalchemy

database = databases.Database("sqlite:///db.sqlite")
metadata = sqlalchemy.MetaData()

# ormar < 0.20
class Album(ormar.Model):
    class Meta:
        database = database
        metadata = metadata
        tablename = "albums"


    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)
    favorite: bool = ormar.Boolean(default=False)

# ormar >= 0.20
class AlbumV20(ormar.Model):
    ormar_config = ormar.OrmarConfig(
        database=database,
        metadata=metadata,
        tablename="albums_v20"
    )

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)
    favorite: bool = ormar.Boolean(default=False)

OrmarConfig api/参数

ormar_config 公开与 Meta 类所提供的相同的设置集。这意味着您可以使用以下任何参数来初始化配置:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
metadata: Optional[sqlalchemy.MetaData]
database: Optional[databases.Database]
engine: Optional[sqlalchemy.engine.Engine]
tablename: Optional[str]
order_by: Optional[List[str]]
abstract: bool
exclude_parent_fields: Optional[List[str]]
queryset_class: Type[QuerySet]
extra: Extra
constraints: Optional[List[ColumnCollectionConstraint]]

BaseMeta 等效项 - 最佳实践

请注意,为了减少代码重复并简化开发,仍然建议创建一个基本配置并为每个模型提供一个副本。 OrmarConfig 为此提供了一种方便的复制方法。

copy 方法接受与 OrmarConfig init 相同的参数,因此您可以根据需要进行覆盖,但默认情况下它将返回已存在的属性,但默认情况下会清除的 tablename、order_by 和约束除外。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import databases
import ormar
import sqlalchemy

base_ormar_config = ormar.OrmarConfig(
    database=databases.Database("sqlite:///db.sqlite"),
    metadata=sqlalchemy.MetaData()
)

class AlbumV20(ormar.Model):
    ormar_config = base_ormar_config.copy(
        tablename="albums_v20"
    )

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)


class TrackV20(ormar.Model):
    ormar_config = base_ormar_config.copy(
        tablename="tracks_v20"
    )

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)

不再支持 options 字段参数。

在版本 0.20 之前,您可以向任何现有的 ormar 字段提供选项参数来限制可接受的值。此功能已被删除,您应该使用为此目的而设计的 ormar.Enum 字段。如果您想保留数据库字段类型(即整数字段),您可以随时编写自定义验证器。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import databases
import ormar
import sqlalchemy

database = databases.Database("sqlite:///db.sqlite")
metadata = sqlalchemy.MetaData()

# ormar < 0.20
class Artist(ormar.Model):
    class Meta:
        database = database
        metadata = metadata


    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)
    country: str = ormar.String(default=False, max_length=50, choices=["UK", "US", "Vietnam", "Colombia"])

# ormar >= 0.20
from enum import Enum

class Country(str, Enum):
    UK = "UK"
    US = "US"
    VIETNAM = "Vietnam"
    COLOMBIA = "Colombia"

class ArtistV20(ormar.Model):
    ormar_config = ormar.OrmarConfig(
        database=database,
        metadata=metadata,
        tablename="artists_v20"
    )

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)
    country: Country = ormar.Enum(enum_class=Country)

pydantic_only 不再支持字段参数

pydantic_only 字段已被弃用并在 v 0.20 中删除。 Ormar 允许像普通 pydantic 模型一样定义 pydantic 场。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import databases
import ormar
import sqlalchemy

database = databases.Database("sqlite:///db.sqlite")
metadata = sqlalchemy.MetaData()

# ormar < 0.20
class Dish(ormar.Model):
    class Meta:
        database = database
        metadata = metadata
        tablename = "dishes"


    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)
    cook: str = ormar.String(max_length=40, pydantic_only=True, default="sam")

# ormar >= 0.20
class DishV20(ormar.Model):
    ormar_config = ormar.OrmarConfig(
        database=database,
        metadata=metadata,
        tablename="dishes_v20"
    )

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)
    cook: str = "sam"  # this is normal pydantic field

不再支持 property_field 装饰器

property_field 装饰器用于提供一种传递模型的字典/序列化 json 表示中包含的计算字段的方法。 pydantic 2.X 版本引入了这种可能性,因此您现在应该切换到 pydantic 原生的版本。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import databases
import ormar
import sqlalchemy
import pydantic

database = databases.Database("sqlite:///db.sqlite")
metadata = sqlalchemy.MetaData()

# ormar < 0.20
class Employee(ormar.Model):
    class Meta:
        database = database
        metadata = metadata


    id: int = ormar.Integer(primary_key=True)
    first_name: str = ormar.String(max_length=100)
    last_name: str = ormar.String(max_length=100)

    @ormar.property_field()
    def full_name(self) -> str:
        return f"{self.first_name} {self.last_name}"

# ormar >= 0.20
class EmployeeV20(ormar.Model):
    ormar_config = ormar.OrmarConfig(
        database=database,
        metadata=metadata,
    )

    id: int = ormar.Integer(primary_key=True)
    first_name: str = ormar.String(max_length=100)
    last_name: str = ormar.String(max_length=100)

    @pydantic.computed_field()
    def full_name(self) -> str:
        return f"{self.first_name} {self.last_name}"

已弃用的方法

下面列出的所有方法均已弃用,并将在 ormar 0.30 版本中删除。

dict() 成为 model_dump()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import databases
import ormar
import sqlalchemy

database = databases.Database("sqlite:///db.sqlite")
metadata = sqlalchemy.MetaData()

class Album(ormar.Model):
    ormar_config = ormar.OrmarConfig(
        database=database,
        metadata=metadata,
        tablename="albums"
    )

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)
    favorite: bool = ormar.Boolean(default=False)

album = Album(name="Dark Side of the Moon")

# ormar < 0.20
album_dict = album.dict()

# ormar >= 0.20
new_album_dict = album.model_dump()

请注意,参数保持不变,即包含、排除等。

json() 成为 model_dump_json()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import databases
import ormar
import sqlalchemy

database = databases.Database("sqlite:///db.sqlite")
metadata = sqlalchemy.MetaData()

class Album(ormar.Model):
    ormar_config = ormar.OrmarConfig(
        database=database,
        metadata=metadata,
        tablename="albums"
    )

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)
    favorite: bool = ormar.Boolean(default=False)

album = Album(name="Dark Side of the Moon")

# ormar < 0.20
album_json= album.json()

# ormar >= 0.20
new_album_dict = album.model_dump_json()

请注意,参数保持不变,即包含、排除等。

construct() 变成 model_construct()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import databases
import ormar
import sqlalchemy

database = databases.Database("sqlite:///db.sqlite")
metadata = sqlalchemy.MetaData()

class Album(ormar.Model):
    ormar_config = ormar.OrmarConfig(
        database=database,
        metadata=metadata,
        tablename="albums"
    )

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)
    favorite: bool = ormar.Boolean(default=False)

params = {
    "name": "Dark Side of the Moon",
    "favorite": True,
}
# ormar < 0.20
album = Album.construct(**params)

# ormar >= 0.20
album = Album.model_construct(**params)

要了解有关构造的更多信息,请参阅 pydantic 文档。