Skip to content

发行说明

0.20.1

✨ 重大变化

  • 请注意,这是 ormar 的第一个非测试版,支持 Pydantic v2。查看 0.20.0 的发行说明和 https://collerek.github.io/ormar/0.20.0b1/migration/

🐛 修复

  • 修复使用 select_lated 和 prefetch_lated 时合并相同目标模型的问题#906
  • 修复与仅 pk 模型相关的保存问题#812
  • 修复多次添加相同的关系会损坏关系缓存#1335

✨ 特点

  • 允许通过 @cmflynn 添加外键索引 #1276

💬其他

  • @Chaoyingz 修复了一些文档,谢谢!

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
    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
    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
    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
    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
    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()

      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" )

      1
      2
      3
      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()

      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" )

      1
      2
      3
      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 文档。

0.12.2

✨ 特点

  • 将 FastAPI 支持提升至最新版本 (0.97.0) #1110
  • 添加对 Python 3.11 的支持和测试#1110

0.12.1

✨ 特点

  • 由于模型和相关模型的递归加载和缓存,加载模型方面的性能得到了巨大提高。 (@erichaydel - 谢谢!)#853

💬 内部结构

  • 比较已实施的趋势变化的性能效果的基准(再次,由@erichaydel - 谢谢!)#853

0.12.0

✨ 重大变化

  • Queryset.bulk_create 现在将在空模型列表上引发 ModelListEmptyError (由 @ponytailer - 谢谢!)#853

✨ 特点

  • Model.upsert() 现在处理一个标志 __force_save__: bool ,允许更新插入模型,无论它们是否设置了主键。请注意,设置此标志将导致对每个更新插入的模型进行两次查询 -> get 检查模型是否存在,并在以后进行相应的更新/插入。第889章

🐛 修复

  • 修复了破坏构造方法的空关系(由 @Abdeldjalil-H - 谢谢!)#870
  • 修复与保存相关的不保存已设置 pks 的模型(包括 uuid)的问题 #885
  • 修复根据排除顺序的错误关系排除#779
  • 修复 property_fields 未正确继承的问题 #774

0.11.3

✨ 特点

  • 在ForeignKey 中记录onupdate 和ondelete 引用操作,并提供ReferentialAction 枚举来指定关系的行为(由@SepehrBazyar - 谢谢!)#724
  • 将 CheckColumn 添加到模型 Meta 中支持的约束(由 @SepehrBazyar - 谢谢!)#729

🐛 修复

  • 修复将查询结果限制为 0 应返回空列表(由 @SepehrBazyar - 谢谢!)#766

💬其他

  • 将黑暗模式添加到文档(由@SepehrBazyar - 谢谢!)#717
  • 更新 aiomysql 依赖项 #778

0.11.2

🐛 修复

  • 修复数据库驱动程序是必需的,而它们应该是可选的 #713
  • 修复 postgres 中没有 limit_raw_sql 标志的限制查询中的布尔字段问题 #704
  • 修复 enum_class 溢出到架构导致 OpenAPI 中的错误 #699

0.11.1

🐛 修复

  • 修复 pydantic 1.9 中引入的深度复制问题 #685

0.11.0

✨ 重大变化

  • 放弃对 python 3.6 的支持
  • Queryset.get_or_create 现在返回一个元组,其中包含模型和布尔值,指示模型是否已创建(由@MojixCoder - 谢谢!)#554
  • Queryset.count() 现在默认计算不同父模型行的数量,可以通过设置 unique=False 来计算所有行(由 @erichaydel - 谢谢)#588

✨ 特点

  • 添加了对 python 3.10 的支持

🐛 修复

  • 修复 save 和bulk_create 中不一致的 JSON 字段行为#584
  • 修复最大递归错误 #580

0.10.25

✨ 特点

  • 将 queryset_class 选项添加到 Model.Meta,使您可以轻松地将 QuerySet 替换为您的模型(由 @ponytailer - 谢谢!)#538
  • 允许将额外的 kwargs 传递给 IndexColumns,这些索引列将传递给 sqlalchemy Index(由 @zevisert - 谢谢)#575

🐛 修复

  • 修复 JSON 字段的可为空设置 #529
  • 修复使用 orjson 而不是 json 时批量操作中的 bytes/str 不匹配问题(由 @ponytailer - 谢谢!)#538

0.10.24

✨ 特点

  • 添加 post_bulk_update 信号(由 @ponytailer - 谢谢!)#524

🐛 修复

  • 修复对 pydantic==1.9.0#502 的支持
  • 修复日期时间的时区问题 #504
  • 删除查询生成中的文字绑定以解锁 postgres 数组 #/tophat/ormar-postgres-extensions/9
  • 修复 JSON 字段的批量更新 #519

💬其他

  • 通过绕过databaseexecute_many 次优实现来提高bulk_create 的性能。 (@Mng-dev-ai 谢谢!)#520
  • 冲击分钟。所需的数据库版本为 >=5.4。

0.10.23

✨ 特点

  • 添加在创建列时将注释传递给 sqlalchemy 的功能 #485

🐛 修复

  • 修复可以为空的 LargeBinary 字段 #409
  • 使 ormar.Model 可供选择 #413
  • 使first()和get()不带参数尊重用户设置的主模型的顺序,回退到主键(分别是asc和desc)#453
  • 修复 postgress 中对非别名连接子句的不正确引用 #455

0.10.22

🐛 修复

  • 设置父 ormar 模型时验证器不被继承的热修复 #365

0.10.21

🐛 修复

  • 添加构造类方法的 ormar 实现,该方法允许在不验证输入的情况下构建模型实例,以加快整个流程(如果您的数据已经经过验证)#318
  • 修复了使用 get_pydantic#365 生成新创建的 pydanic 模型时从 ormar 模型“继承”字段验证器的问题

0.10.20

✨ 特点

  • 在 Model.Meta 中添加额外参数,该参数接受 Extra.ignore 和 Extra.forbid(默认),并且忽略传递给 ormar 模型的额外字段,或者在遇到异常时引发异常 #358

🐛 修复

  • 如果字段可为空并且设置了选项,则不允许“无”#354
  • 无论自动增量和显式可为空设置如何,始终将 Primary_key 设置为非空,以避免迁移问题 #348

0.10.19

✨ 特点

  • 在 Meta.constraints#307 中添加对多列非唯一 IndexColumns 的支持
  • 添加 sql_nullable 字段属性,允许为 pydantic 模型和底层 sql 列设置不同的可为空设置 #308

🐛 修复

  • 启用关系图缓存以提高性能 #337
  • 澄清并修复有关可为空字段的文档 #339

💬其他

  • 将支持的数据库版本升级到 <=5.2。

0.10.18

🐛 修复

  • 修复 pydantic 模型中的字段顺序 #328
  • 修复数据库 0.5.0 支持 #142

0.10.17

✨ 特点

  • 允许覆盖模型字段的默认 pydantic 类型 #312
  • 添加对 sqlalchemy >=1.4 的支持(需要数据库 >= 0.5.0)#142

0.10.16

✨ 特点

  • 允许将您自己的 pydantic 配置传递给 ormar.Model ,该模型将由 @naturalethic 与默认配置合并(谢谢!)#285
  • 通过 @ProgrammerPlus1998 添加 SmallInteger 字段类型(谢谢!)#297

🐛 修复

  • 通过删除直接在模式 #291 中公开的过时的 pydantic 字段参数来修复生成 openapi 模式
  • 修复通过模型自动生成的不必要的警告 #295

0.10.15

🐛 修复

  • 修复使用嵌套模型生成 pydantic 模型树的问题(由 @pawamoy - 谢谢!)#278
  • 修复有关缺少主键字段的警告中缺少的 f 字符串 #274
  • 修复将外键值作为关系传递(额外的保护,已在最新版本中修复)#270

0.10.14

✨ 特点

  • 允许将 timezone:bool = False 参数传递给时区感知数据库列的 DateTime 和 Time 字段 #264
  • 允许在 DateTime、Time 和 Date 字段上传递日期时间、日期和时间进行过滤,以允许按日期时间进行过滤,而不是将值转换为字符串 #79

🐛 修复

  • 修复从 psycopg2 到 psycopg2-binary 的依赖关系#255

0.10.13

✨ 特点

  • 允许在 select_lated 和 prefetch_lated 中传递字段访问器。 python 风格 select_related#225.

    • 之前:

      await Post.objects.select_related(["author", "categories"]).get() await Author.objects.prefetch_related("posts__categories").get()

    • 现在还:

      await Post.objects.select_related([Post.author, Post.categories]).get() await Author.objects.prefetch_related(Author.posts.categories).get()

🐛 修复

  • 修复覆盖继承主键的默认值 #253

0.10.12

🐛 修复

  • 修复 QuerySet.create 方法不使用 init (如果提供自定义)#245
  • 修复 ForwardRefManyToMany 关系设置错误的 pydantic 类型 #250

0.10.11

✨ 特点

  • 将values和values_list添加到QuerySet和QuerysetProxy,允许从查询#223返回原始数据。
    • 允许从查询返回元组列表或字典列表
    • 跳过将数据解析为 ormar 模型,因此也跳过验证
    • 允许排除关系链之间的模型,因此您可以仅提取所需的列
    • 如果仅提取一列,values_list 允许您展平结果。

🐛 修复

  • 修复使用 ForwardRef #226 通过 m2m 关系模型创建自动的问题

0.10.10

✨ 特点

  • 添加 get_pydantic 标志,允许您从 ormar.Model 自动生成等效的 pydantic 模型树。这个新生成的模型树可在请求和响应中使用,以排除您不想包含在数据中的字段。
  • 在模型 Meta 中添加 except_parent_fields 参数,允许您在继承过程中从父模型中排除字段。请注意,最佳实践是将模型和 mixins 结合起来,但如果您有许多相似的模型,而只有一个不同的模型,那么它可能是实现这一目标的有用工具。

🐛 修复

  • 修复了具有分页和关系的空过滤器(由 @erichaydel 提供)#214
  • 修复如果在 #216 之前未保存,则不会在关系的反面保存子对象

💬其他

  • 展开文档的 fastapi 部分以显示在 fastapi 的请求和响应中使用 ormar 的示例。
  • 改进有关默认值、ForeignKey.add 等的文档。

0.10.9

重要的安全修复

  • 更新 pydantic 引脚以修复安全漏洞 CVE-2021-29510

建议您更新到已修补的 pydantic 版本。在 0.10.9 中,ormar 排除了固定依赖项中存在漏洞的版本。

🐛 修复

  • 修复 LargeBinary 的 OpenAPI 架构 #204

0.10.8

🐛 修复

  • 修复 pk_only 子模型中的填充默认值 #202
  • 使用 base64 str 表示修复 LargeBinary 字段的 mypy #199
  • 修复具有 Base64 str 表示形式的 LargeBinary 字段的 OpenAPI 架构格式 #199
  • 修复具有 Base64 str 表示形式的 LargeBinary 字段的 OpenAPI 选择编码

0.10.7

✨ 特点

  • 添加 exclude_primary_keys: bool = False 标记为 dict() 方法,允许排除结果词典中的所有主键列。第164章
  • 添加 exclude_through_models: bool = False dict() 的标志,允许从 ManyToMany 关系中排除所有模型 #164
  • 添加 represent_as_base64_str: bool = False 允许将字节 LargeBinary 字段转换为 base64 编码字符串的参数。在访问属性时,字符串在 dict() 中返回,字符串在设置时转换为字节。数据库中的数据以字节存储。第187章
  • 添加 pk 别名以允许 Model.pk 在过滤器和 order by 子句中访问字段(python 风格)

🐛 修复

  • 删除 LargeBinary 字段的 max_length 的默认 None 选项 #186
  • 删除字符串字段 max_length 的默认 None 选项

💬其他

  • 在文档中提供 dict() 参数的指南和示例
  • 将魔法方法中获取/设置属性的主要重构为描述符 -> 显着的性能改进

0.10.6

✨ 特点

  • 添加 LargeBinary(max_length) 字段类型 #166

  • 添加对普通 pydantic 字段(包括模型)的支持,而不是 pydantic_only 属性,该属性现已弃用 #160。 Pydantic 字段应该像在 ormar 字段旁边的 pydantic 模型中一样正常声明,请注意(显然)ormar 不会在数据库中保存和加载该字段的值,这意味着以下之一必须为真:

    • 在 ormar 模型上声明的 pydantic 字段必须是可选的(默认为 None)
    • pydantic 字段必须设置默认值
    • pydantic 字段具有 default_factory 函数集
    • 具有 pydantic 字段的 ormar.Model 必须覆盖 __init__() 并在那里提供值

    如果上述 ormar (或者更确切地说 pydantic)在从数据库加载数据期间都不会失败,并且缺少声明的 pydantic 字段所需的值。

  • Ormar 现在提供了 openapi 模式中有意义的示例,包括嵌套模型。使用与 dict() 和 select/load_all 相同的算法来迭代相关模型,无需查看。示例也出现在 fastapi 中。第157章

🐛 修复

  • 默认情况下,pydantic 在分配期间不会验证字段,这对于 ORM 来说不是理想的设置,现在所有 ormar.Models 在分配期间都打开了验证(例如 model.column = 'value')

💬其他

  • 在 readme #180 的 QuickStart 中添加连接到数据库
  • OpenAPI 架构不再包含 ormar.Model 文档字符串作为描述,如果您不提供自己的文档字符串,则仅提供模型名称。
  • 一些性能改进。

0.10.5

🐛 修复

  • 修复 fastapi-pagination 中的错误#73
  • 删除 QuerySet.all() 和 Querysetproxy.all() 返回值中 List[Optional[T]] 中不必要的Optional #174
  • 运行测试覆盖率仅在内部prs上发布,而不是在github操作中发布。

0.10.4

✨ 特点

  • 添加Python风格 filterorder_by 使用字段访问而不是 dunder 分隔的字符串。第51章
    • 通过属性访问(点符号链)访问字段可用于构造 FilterGroups(ormar.and_ 和 ormar.or_)
    • 字段访问重载了一组 Python 运算符,并提供了一组函数来允许与 **kwargs 中 dunder 分隔的参数名称相同的功能,这意味着从与模型 Album 相关的示例模型 Track 中查询现在您有更多选项:
      • 精确 - 与值精确匹配,sql 列 =
        • 旧:album__name__exact='Malibu'
        • 新:也可以写成 Track.album.name == 'Malibu
      • iexact - 精确匹配 sql 列 = (不区分大小写)
        • 旧:album__name__iexact='malibu'
        • 新:也可以写成 Track.album.name.iexact('malibu')
      • 包含 - sql 列 LIKE '%%'
        • 旧:album__name__contains='Mal'
        • 新:也可以写为 Track.album.name % 'Mal')
        • 新:也可以写成 Track.album.name.contains('Mal')
      • icontains - sql 列 LIKE '%%' (不区分大小写)
        • 旧:album__name__icontains='mal'
        • 新:也可以写成 Track.album.name.icontains('mal')
      • 在-sql中 column IN (<VALUE1>, <VALUE2>, ...)
        • 老的: album__name__in=['Malibu', 'Barclay']
        • 新:也可以写成 Track.album.name << ['Malibu', 'Barclay']
        • 新:也可以写成 Track.album.name.in_(['Malibu', 'Barclay'])
      • isnull - sql 列 IS NULL(并且 sql 列 IS NOT NULL)
        • 旧:album__name__isnull=True(isnotnullalbum__name__isnull=False)
        • 新:也可以写为 Track.album.name >> 无
        • 新:也可以写成 Track.album.name.isnull(True)
        • 新:not null 也可以写成 Track.album.name.isnull(False)
        • 新:not null 也可以写成 ~(Track.album.name >> None)
        • 新:not null 也可以写成 ~(Track.album.name.isnull(True))
      • gt - sql 列 > (大于)
        • 旧:position__gt=3
        • 新:也可以写为 Track.album.name > 3
      • gte - sql 列 >= (大于或等于)
        • 旧:position__gte=3
        • 新:也可以写为 Track.album.name >= 3
      • lt - sql 列 < (低于)
        • 旧:position__lt=3
        • 新:也可以写为 Track.album.name < 3
      • lte - sql 列 <= (低于等于)
        • 旧:position__lte=3
        • 新:也可以写为 Track.album.name <= 3
      • startswith - sql 列 LIKE '%' (精确开始匹配)
        • 旧:album__name__startswith='Mal'
        • 新:也可以写成 Track.album.name.startswith('Mal')
      • istartswith - sql 列 LIKE '%'(不区分大小写)
        • 老的: album__name__istartswith='mal'
        • 新:也可以写成 Track.album.name.istartswith('mal')
      • endswith - sql 列 LIKE '%' (完全结束匹配)
        • 旧:album__name__endswith='ibu'
        • 新:也可以写成 Track.album.name.endswith('ibu')
      • iendswith - sql 列 LIKE '%' (不区分大小写)
        • 旧:album__name__iendswith='IBU'
        • 新:也可以写成 Track.album.name.iendswith('IBU')
  • 您不仅可以在 filter() 和 except() 中提供 FilterGroups,还可以在:
    • 得到()
    • 获取或无()
    • 获取或创建()
    • 第一的()
    • 全部()
    • 删除()
  • 通过 FilterGroups(ormar.and_ 和 ormar.or_),您现在可以使用:
    • & - 作为 and_ 而不是下一层嵌套
    • | - 作为“or_”而不是下一层嵌套
    • ~ - 作为过滤器组的否定
  • 要将多组过滤器合并为一组条件,请使用 & (sql AND) 和 | (sql 或)

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    # Following queries are equivalent:
    # sql: ( product.name = 'Test'  AND  product.rating >= 3.0 )
    
    # ormar OPTION 1 - OLD one
    Product.objects.filter(name='Test', rating__gte=3.0).get()
    
    # ormar OPTION 2 - OLD one
    Product.objects.filter(ormar.and_(name='Test', rating__gte=3.0)).get()
    
    # ormar OPTION 3 - NEW one (field access)
    Product.objects.filter((Product.name == 'Test') & (Product.rating >=3.0)).get()
    
  • 同样适用于嵌套的复杂过滤器

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    # Following queries are equivalent:
    # sql: ( product.name = 'Test' AND product.rating >= 3.0 ) 
    #       OR (categories.name IN ('Toys', 'Books'))
    
    # ormar OPTION 1 - OLD one
    Product.objects.filter(ormar.or_(
                              ormar.and_(name='Test', rating__gte=3.0), 
                              categories__name__in=['Toys', 'Books'])
                          ).get()
    
    # ormar OPTION 2 - NEW one (instead of nested or use `|`)
    Product.objects.filter(
                          ormar.and_(name='Test', rating__gte=3.0) | 
                          ormar.and_(categories__name__in=['Toys', 'Books'])
                          ).get()
    
    # ormar OPTION 3 - NEW one (field access)
    Product.objects.filter(
                          ((Product.name='Test') & (Product.rating >= 3.0)) | 
                          (Product.categories.name << ['Toys', 'Books'])
                          ).get()
    
  • 现在您还可以使用字段访问来向 order_by() 提供 OrderActions

    • 升序排列:
      • 老的: Product.objects.order_by("name").all()
      • 新的: Product.objects.order_by(Product.name.asc()).all()
    • 降序排列:
      • 老的: Product.objects.order_by("-name").all()
      • 新的: Product.objects.order_by(Product.name.desc()).all()
    • 当然,您也可以组合不同的模型和许多 order_by: Product.objects.order_by([Product.category.name.asc(), Product.name.desc()]).all()

🐛 修复

  • 并不是真正的错误,而是不一致。提供带有嵌套模型的过滤器,即 album__category__name = 'AA' 正在检查专辑和类别模型是否包含在 select_lated() 中,如果没有,则会自动将它们添加到那里。相同的功能不适用于 FilterGroups(and_ 和 or_),现在它可以工作(也适用于返回 FilterGroups 的 python 样式过滤器)。

0.10.3

✨ 特点

  • foreignKey和ManyToMany现在支持skip_reverse:bool = False标志#118。如果您在内部设置了skip_reverse标志,该字段仍然注册在关系的另一端,因此您可以:

    • 按反向模型中的相关模型字段进行过滤
    • order_by by 反向模型中的相关模型字段

    但你不能:

    • 使用 related_name 从反向模型访问相关字段
    • 即使您从模型的反面选择相关,返回的模型也不会填充在反向实例中(不会阻止连接,因此您仍然可以过滤和 order_by)
    • 该关系不会填充到 dict() 和 json() 中
    • 从 dict() 或 json() (也通过 fastapi)填充时无法传递嵌套的相关对象。根据 pydantic 配置中的额外设置,它将被忽略或引发错误。
    • Model.save_lated() 现在可以一次保存整个数据树 #148 意思是:

    • 它知道是否应该首先保存主模型或相关模型以保留关系

    • 它保存主模型如果

      • 它没有保存,
      • 没有pk值
      • 或 save_all=True 标志已设置

      在这些情况下,您不必将保存分成两个调用(save() 和 save_lated())

    • 它还支持多对多关系

    • 它还支持 m2m 关系的可选 Through 模型值

  • 添加通过模型关系字段名称进行自定义的可能性。

  • 默认情况下,通过模型关系名称默认为小写的相关模型名称。所以在这样的例子中:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    ... ## course declaration omitted
    class Student(ormar.Model):
        class Meta:
            database = database
            metadata = metadata
    
        id: int = ormar.Integer(primary_key=True)
        name: str = ormar.String(max_length=100)
        courses = ormar.ManyToMany(Course)
    
    ## will produce default Through model like follows (example simplified)
    class StudentCourse(ormar.Model):
        class Meta:
            database = database
            metadata = metadata
            tablename = "students_courses"
    
        id: int = ormar.Integer(primary_key=True)
        student = ormar.ForeignKey(Student) ## default name
        course = ormar.ForeignKey(Course)  # default name
    
  • 要自定义 Through 模型中的字段/关系名称,现在您可以使用 ManyToMany 的新参数:

    • through_relation_name - 通向声明 ManyToMany 的模型的字段名称
    • through_reverse_relation_name - 通向 ManyToMany 通向的模型的字段名称

    例子:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    ... # course declaration omitted
    class Student(ormar.Model):
        class Meta:
            database = database
            metadata = metadata
    
        id: int = ormar.Integer(primary_key=True)
        name: str = ormar.String(max_length=100)
        courses = ormar.ManyToMany(Course,
                                   through_relation_name="student_id",
                                   through_reverse_relation_name="course_id")
    
    # will produce default Through model like follows (example simplified)
    class StudentCourse(ormar.Model):
        class Meta:
            database = database
            metadata = metadata
            tablename = "students_courses"
    
        id: int = ormar.Integer(primary_key=True)
        student_id = ormar.ForeignKey(Student) # set by through_relation_name
        course_id = ormar.ForeignKey(Course)  # set by through_reverse_relation_name
    

🐛 修复

  • 修复weakref ReferenceError错误#118
  • 修复设置 pydantic Config.extra="forbid" 时由 Through fields 引发的错误
  • 修复 pydantic.PrivateAttr 未在 __init__ 处初始化的错误#149
  • 修复 dict() 中 pydantic-type 排除的错误,且 __all__ 键不起作用

💬其他

  • 引入模型的 sqlalchemy-to-ormar 自动翻译器的链接
  • 提供支持 ormar 的 fastapi 生态系统库的链接
  • 将交易添加到文档(数据库支持)

0.10.2

✨ 特点

  • Model.save_related(follow=False) 现在还接受两个附加参数: Model.save_related(follow=False, save_all=False, exclude=None)
    • save_all:bool -> 默认情况下(因此 save_all=False)ormar 仅更新插入未保存的模型(因此是新的或更新的模型),使用 save_all=True 所有相关模型都会保存,无论保存状态如何,这在以下情况下可能很有用更新的模型来自api调用,因此在后端不会改变。
    • exclude: Union[Set, Dict, None] -> 设置/字典要从保存中排除的关系,即使使用 follow=True 和 save_all=True 也不会保存这些关系。要排除嵌套关系,请传递嵌套字典,例如: exclude={"child":{"sub_child": {"exclude_sub_child_realtion"}}} 。允许的值遵循 fields/exclude_fields (来自 QuerySet)方法架构,因此当有疑问时,您可以参考查询中的文档 -> 选择字段子集 -> 字段。
  • Model.update() 方法现在接受 _columns: List[str] = None 参数,该参数接受要更新的列名列表。如果通过,则仅那些列将在数据库中更新。请注意, update() 不会刷新模型的实例,因此,如果您更改的列数多于在 _columns 列表中传递的列数,您的模型实例将具有与数据库不同的值!
  • Model.model_dump() 方法以前仅包含直接相关模型或嵌套模型(如果它们不可为空且不是虚拟的),现在所有先前未在没有循环的情况下访问的相关模型都包含在 dict() 中。这应该不会破坏,因为更多的数据将被转储到字典中,但它不应该丢失。
  • QuerySet.delete(each=False, **kwargs) 以前要求您传递一个过滤器(通过 **kwargs 或作为单独的filter() 调用)或设置each=True 现在也接受生成NOT 过滤器的exclusive() 调用。因此,需要设置each=True 来删除整个表或至少一个过滤/排除子句。
  • 同样的事情也适用于 QuerySet.update(each=False, **kwargs) 之前也要求您传递一个过滤器(通过 **kwargs 或作为单独的 filter() 调用)或设置each=True 现在也接受生成 NOT 过滤器的 except() 调用。因此,需要设置each=True 来更新整个表或至少一个过滤/排除子句。
  • 同样的事情也适用于 QuerysetProxy.update(each=False, **kwargs) 之前也要求您传递一个过滤器(通过 **kwargs 或作为单独的 filter() 调用)或设置each=True 现在也接受生成 NOT 过滤器的 except() 调用。因此,需要设置each=True 来更新整个表或至少一个过滤/排除子句。

🐛 修复

  • 如果 fk 列具有不同的数据库别名,则修复 QuerysetProxy 中不正确的关系字段解析。
  • 修复了调用 dict() 时带有循环的非常复杂模型结构的递归错误。
  • 修复当两个非关系字段不是关系字段(即 JSON)时在查询结果中合并(附加)时的错误
  • 修复从列表翻译为字典期间在链中使用相同关系名称但导致不同模型的错误
  • 修复bulk_create尝试保存property_field修饰方法和pydantic字段时的错误
  • 修复反向关系的深层嵌套链的错误合并

💬其他

  • 性能优化
  • 根据测试区域将测试拆分为包

0.10.1

特征

  • 将 get_or_none(**kwargs) 方法添加到 QuerySet 和 QuerysetProxy。它与 get(**kwargs) 完全相同,但如果没有与条件匹配的数据库记录,则 get_or_none 不会引发 ormar.NoMatch 异常,而是简单地返回 None 。

修复

  • 修复 order_by 子句中与方言相关的列名和表名引用在 postgres 中无法正常工作的问题。

0.10.0

打破

  • 删除了对长期不推荐使用的字段定义表示法的支持,在该表示法中您使用 ormar 字段作为类型提示,即 test_field: ormar.Integger() = None
  • 改进的类型提示 -> mypy 可以正确解析相关模型字段(ForeignKey 和 ManyToMany)以及 QuerySet 方法的返回类型。那些提到的现在返回正确的模型(即 Book)而不是 ormar.Model 类型。关系和 QuerysetProxy 方法的反面仍然存在问题,为了缓解现在返回 Any 的类型提示。部分修复#112。

特征

  • 添加 select_all(follow: bool = False) QuerySet 和 QuerysetProxy 的方法。它类似于模型的 load_all() 方法,但可以直接在查询中使用。默认情况下 select_all() 仅添加直接相关的模型,如果 follow=True 也会添加相关模型的相关模型,而不会在关系中出现循环。请注意,它不是并结束异步模型,因此您仍然必须发出 get()、all() 等,因为 select_all() 返回像 fields() 或 order_by() 这样的 QuerySet(或代理)。

内部结构

  • ormar 字段不再存储为 Meta.model_fields 字典中的类,而是存储为实例。

0.9.9

特征

  • 添加更改关系和模型的默认顺序的可能性。
    • 要更改模型排序,请传递orders_by = [columns] where columns: List[str] 到模型元类
    • 要更改关系 order_by,请传递 order_by = [columns] where columns: List[str]
    • 要更改反向关系 order_by 传递 related_orders_by = [columns] where columns: List[str]
    • 参数可以是列名称或 -{col_name} 以降序排序
    • 在关系中,您只能按直接相关的模型列进行排序,或者对于多对多列也可以通过模型列进行排序 "{through_field_name}__{column_name}"
    • order_by 子句的应用顺序如下:
      • 在查询中显式传递 order_by() 调用
      • 如果存在则关系通过orders_by
      • 模型元类orders_by
      • 模型主键列 asc(后备,如果以上均未提供则使用)
  • 添加 4 个新的聚合函数 -> min、max、sum 和 avg 分别是它们的 相应的 sql 等价物。
    • 您可以传递一个或多个列名称,包括相关列。
    • 截至目前,传递的每一列都是单独聚合的(因此 sum(col1+col2) 是不可能的,您可以使用 sum(col1, col2) ,然后在 python 中添加 2 个返回的总和)
    • 您不能对非数字列进行求和和求平均值
    • 如果对一列进行聚合,则直接返回单个值作为结果
    • 如果您聚合多个列,则返回带有 column: 结果对的字典
  • 添加 4 个新信号 -> pre_relation_add、post_relation_add、pre_relation_remove 和 post_relation_remove
    • 新添加的信号针对 ManyToMany 关系(双方)和foreignkey 关系的反面(与公开的 QuerysetProxy 相同)发出。
    • 信号接收以下参数: sender: Type[Model] - 发送者类,instance: Model - 添加相关模型的实例,child: Model - 正在添加的模型,relation_name: str - 添加子项的关系的名称,例如添加信号也通过了_kwargs:字典 - 传递给 add() 的 kwargs 字典

变化

  • 现在,通过在创建、删除和更新时实例化多对多关系的模型,因此您不仅可以提供自动增量 int 作为主键,还可以提供任何具有默认功能的列类型。
  • 由于现在已经实例化了 Through 模型,因此您还可以订阅 Through 模型前/后保存/更新/删除信号
  • pre_update 信号接收器现在还获得 Passed_args 参数,它是传递给更新函数的值的字典(如果有的话)(否则为空字典)

修复

  • 现在,在提取值之前发送 pre_update 信号,以便您可以就地修改传递的实例,并且修改的字段值将反映在数据库中
  • bulk_update 现在也可以正确使用 UUID 主键列类型

0.9.8

特征

  • 添加对数据库中选定字段进行加密的可能性
    • 至少您需要提供 encrypt_secret 和 encrypt_backend
    • encrypt_backend 可以是 ormar.EncryptBackends 枚举之一(NONE、FERNET、HASH、CUSTOM) - 默认值:NONE
    • 选择自定义后端时,您需要提供子类 ormar.fields.EncryptBackend 的后端类
    • 您无法加密 Primary_key 列和关系列(FK 和 M2M)。
    • 提供了 2 个后端:HASH 和 FERNET
      • HASH 是一种单向哈希(如密码),在检索时永远不会解密
      • FERNET 是双向加密/解密后端
    • 请注意,在 FERNET 后端中,您完全失去了过滤的可能性,因为加密值的一部分是时间戳。
    • 请注意,在 HASH 后端中,您可以按完整值进行过滤,但像 contains 这样的过滤器将不起作用,因为对加密值进行比较
    • 请注意,添加 encrypt_backend 会将数据库列类型更改为 TEXT,需要通过迁移或手动更改在 db 中反映

修复

  • (高级/内部)恢复停止工作的自定义 sqlalchemy 类型(通过 types.TypeDecorator 子类)功能,因此从未调用 process_result_value

0.9.7

特征

  • 添加 isnull 运算符来过滤和排除方法。

    1
    2
    album__name__isnull=True #(sql: album.name is null)
    album__name__isnull=False #(sql: album.name is not null))
    
  • 添加可用于组合的 ormar.or_ 和 ormar.and_ 函数 具有嵌套条件的复杂查询。 示例查询:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    books = (
        await Book.objects.select_related("author")
        .filter(
            ormar.and_(
                ormar.or_(year__gt=1960, year__lt=1940),
                author__name="J.R.R. Tolkien",
            )
        )
        .all()
    )
    

    检查查询中更新的文档 -> 过滤和排序 -> 复杂过滤器

其他

  • 在ForeignKey或ManyToMany上设置默认值会引发ModelDefinition异常,因为它现在(并且过去)不受支持

0.9.6

##重要的

  • 通过多对多关系模型现在变得可选。这不是一个重大变化,因为如果您提供它,一切都会像以前一样正常工作。因此,如果您不想或不需要“通过”模型上的任何其他字段,您可以跳过它。请注意,它将自动为您创建,并且仍然必须包含在 alembic 迁移的示例中。如果您想删除现有数据库,请检查默认命名约定以调整现有数据库结构。

    请注意,如果您想自定义 Through 模型名称或数据库表名称,您仍然需要提供它。

特征

  • 向 QuerysetProxy 添加更新方法,因此现在可以直接从 ManyToMany 关系中的父模型以及反向外键关系中更新相关模型。请注意,像 QuerySetupdate 中的更新会返回更新模型的数量,并且不会更新父模型上的相关模型。要获取父模型上刷新的数据,您需要刷新相关模型(即 await model_instance.related.all()
  • 添加 load_all(follow=False, exclude=None) model 方法,允许在一次调用中加载模型的当前实例以及所有相关模型。默认情况下,它仅加载直接相关的模型,但设置 follow=True 会导致遍历树(避免循环)。您还可以传递与 QuerySet.exclude_fields() 方法相同的排除参数。
  • 添加了在多对多关系的 Through 模型上添加更多字段的可能性:
    • through 模型字段的名称是 Through 类的小写名称
    • 您可以在关系上调用 add(child, **kwargs) 时传递其他字段(在 QuerysetProxy 上)
    • 当关键字参数之一应该是带有值字典的模型名称时,您可以在关系上(在 QuerysetProxy 上)调用 create(**kwargs) 时传递其他字段
    • 您可以通过模型字段订购
    • 您可以通过模型字段进行过滤
    • 您可以通过模型包含和排除字段
    • through 模型仅附加到相关模型(即,如果您从 A 查询到 B -> 仅在 B 上)
    • 请注意,直通模型是在没有关系的情况下显式加载的 -> 关系已填充在 ManyToMany 字段中。
    • 请注意,就像之前您无法通过模型声明关系字段一样,它们将由 ormar 为您填充,但现在如果您尝试这样做,将会抛出 ModelDefinitionError
    • 检查更新的 ManyToMany 关系文档以获取更多信息

其他

  • 更新了文档和 API 文档
  • 重构和优化主要涉及过滤器、排除和排序依据

0.9.5

修复

  • 修复 pydantic 更新到版本 >=1.8 后创建 pydantic FieldInfo 的问题
  • 固定所需的依赖版本以避免将来出现此类情况

0.9.4

修复

  • 修复当多个模型引用相同相关模型时自动文档的 fastapi OpenAPI 模式生成

0.9.3

修复

  • 修复初始化后设置值时 JSON 字段被双重转义的问题
  • 修复由于 pydantic 内部结构而导致 JSON 字段不遵守可为空字段设置的问题
  • 修复 JSON 字段的选择验证
  • 修复初始化后设置属性时未验证的选项
  • 修复在 QuerySet 更新调用期间未验证的选项

0.9.2

其他

  • 更新了文档/自述文件中的快速入门
  • 更新了文档,其中包含查询子页面的链接
  • 添加了代码气候和下载量的徽章

0.9.1

特征

  • 将选项值添加到 OpenAPI 规范中,使其看起来像结果架构中的本机 Enum 字段。

修复

  • 当特殊字段尚未初始化但作为字符串等传递时,使用 fastapi 使用修复选择行为。

0.9.0

重要的

  • 制动修复:版本 0.8.0 引入了一个错误,该错误会阻止在数据库中生成foreign_keys约束,无论是在alembic中还是在通过sqlalchemy.engine创建期间,该问题现已修复。
  • 因此,如果您使用版本 >=0.8.0,强烈建议您更新,因为尽管大多数 ormar 函数正在运行,但使用 ormar (或 ormar + alembic)创建的数据库没有关系,并且从性能和数据的角度来看会受到影响正直。
  • 如果您使用 ormar 连接到现有数据库,您的性能和完整性应该很好,但您应该进行更新以反映模型中所有未来的架构更新。

打破

  • 突破:所有外键和唯一约束现在都有一个名称,因此 alembic 可以在数据库中识别它们而不依赖于数据库
  • 破坏:在模型构造期间,如果模型的元类不包含元数据或数据库,现在将引发 ModelDefinitionError 而不是通用 AttributeError。
  • 破坏:用于运行查询的编码/数据库没有用于 sqlite 后端的连接池,这意味着每个查询都使用新连接运行,并且无法启用强制外键约束,因为默认情况下在每个连接上关闭这些约束。自 >=0.9.0 起,这在 ormar 中发生了变化,默认情况下每个 sqlite3 查询都有“PRAGMAforeign_keys=1;”运行,这样现在每个 sqlite3 连接默认都会强制执行外键约束,包括级联。

其他

  • 更新 API 文档。
  • 添加在数据库中创建 fk 和在数据库中级联的测试

0.8.1

特征

  • 介绍关系中ForwardRef的处理。现在您可以创建自引用模型 - 外键和多对多关系。 ForwardRef 可用于 to 和 throughModel。
  • 引入在一个查询中执行两个相同关系连接的可能性,以便处理复杂关系,例如:

    1
    2
    3
    4
    5
    6
    7
        B = X = Y
      //
     A 
      \
        C = X = Y <= before you could link from X to Y only once in one query
                     unless two different relation were used 
                     (two relation fields with different names)
    
  • 引入分页方法,允许按页面和 page_size 限制/偏移。可用于 QuerySet 和 QuerysetProxy。

其他

  • 查询和连接中的重构和性能优化。
  • 将 python 3.9 添加到测试和 pypi 设置中。
  • 更新 API 文档和文档 ->,即查询文档的拆分。

0.8.0

打破

  • Breaking:remove() 反向外键关系中子端的父级现在需要传递一个关系名称,因为同一个模型可以注册多次,并且 ormar 需要知道您想要从父级的哪个关系中删除子级。
  • 打破:默认情况下,使用 select_lated 应用限制和偏移量仅应用于连接之前的主表 -> 意味着不是总行数受到限制,而只是主模型的数量(查询中的第一个,用于构造它)。您仍然可以在限制或偏移量(或两者)上使用 limit_raw_sql=True 标志来限制数据库响应中的所有行
  • 破坏:发出first()现在会获取按主键asc排序的第一行(因此插入的第一个行(对于非数字主键可能不同 - 即字符串的字母顺序))
  • 破坏:发出不带任何过滤器的 get() 现在会获取按主键 desc 排序的第一行(因此应该是最后插入的行(对于非数字主键可能不同 - 即字符串的字母顺序))
  • 破坏(内部):保留在 Meta.columns 中的 sqlalchemy 列不再绑定到表,因此您无法直接从那里获取列

特征

  • 引入继承。目前有两种类型的继承是可能的:
    • Mixins - 不要子类化 ormar.Model,只需定义稍后在不同模型上使用的字段(例如每个子模型上的created_date 和updated_date),只有实际模型创建表,但添加 mixins 中的那些字段
    • 具体表继承 - 意味着父级在 Meta 类中被标记为abstract=True,并且每个子级都有自己的表,其中包含来自父级的列和自己的子级列,有点类似于 Mixins,但父级也是一个(抽象)模型
    • 要了解更多信息,请查看有关模型 -> 继承部分的文档。
  • QuerySet first() 可以与 prefetch_lated 一起使用

修复

  • 修复主要模型 order by 的 order_by 中的小错误
  • 修复同一模型的多个 related_names 的 prefetch_query。
  • 修复在不同模型上使用相同的 related_name 导致相同的相关模型相互覆盖的问题,现在引发 ModelDefinitionError 并且您需要更改名称。
  • 修复了应用多个联接到同一个表时 order_by 覆盖条件的问题。

文档

  • 文档中的拆分和清理:
    • 将模型部分分为几个小部分
    • 将关系部分分为小节
    • 将字段部分划分为小部分
  • 添加模型继承部分
  • 添加API(测试版)文档

0.7.5

  • 修复了 Many_to_many 关系连接中错误的关系列名称(修复 #73)

0.7.4

  • 允许与同一相关模型/表存在多个关系。
  • 修复了 Many_to_many 关系连接中使用的错误关系列(修复 #73)
  • 修复了当同一模型也存在 fk 关系时 m2m 关系的错误关系群体。
  • 如果一个模型上的同一个表存在多个关系,则添加检查用户是否提供 related_name。
  • 更加急切地清理死掉的弱代理模型。

0.7.3

  • 修复了使用 UUDI pk 设置获取相关模型的问题,UUDI pk 是原始字符串(修复 #71)

0.7.2

  • 修复仅使用 pk 覆盖相关模型的问题 Model.update() with fields passed as parameters (修复#70)

0.7.1

  • 修复仅在 Model.save() 中使用 pk 覆盖相关模型的问题(修复 #68)

0.7.0

  • 破坏:QuerySetbulk_update 方法现在会针对传递的未保存模型引发 ModelPersistenceError,而不是 QueryDefinitionError
  • 突破:使用未知字段名称的模型初始化现在会引发 ModelError 而不是 KeyError
  • 添加了信号,具有预定义的列表信号和装饰器:post_delete、post_save、post_update、pre_delete、pre_save、pre_update
  • 添加 py.typed 并修改 setup.py 以支持 mypy
  • 性能优化
  • 更新文档

0.6.2

  • 性能优化
  • 修复了需要 pydantic_only 字段的错误
  • 添加 property_field 装饰器,将函数注册为属性,该属性将包含在 Model.model_dump() 和 fastapi 响应中
  • 更新文档

0.6.1

  • 显式设置 None 以排除可为空的字段,以避免 pydantic 设置默认值(修复 #60)。

0.6.0

  • 破坏:从数据库中删除实例行时调用instance.load()现在会引发NoMatch而不是ValueError
  • 破坏:在 ReverseForeignKey 关系上调用添加和删除现在会更新数据库设置/删除 fk 列中的子模型
  • 突破:ReverseForeignKey 关系现在像 ManyToMany 关系一样公开 QuerySetProxy API
  • 破坏:从 ManyToMany 查询相关模型会清除父模型上加载的相关模型列表:
    • 示例: post.categories.first() 将把 post.categories 设置为 1 个相关模型的列表 -> first() 返回的模型
    • 示例 2:如果帖子有 4 个类别,则 len(post.categories) == 4 调用 post.categories.limit(2).all() -> 现在只会加载 2 个子进程 assert len(post.categories) == 2
  • 向 QuerySetProxy 添加了 get_or_create、update_or_create、fields、exclude_fields、exclusion、prefetch_lated 和 order_by,因此现在您可以直接从关系中使用这些方法
  • 更新文档

0.5.5

  • 修复了迁移 UUID 列的 alembic 自动生成问题。它应该只生成 sqlalchemy CHAR(32) 或 CHAR(36)
  • 为了使其工作,您必须设置 user_module_prefix='sa'。 (必须等于 sqlalchemy_module_prefix 选项(默认为“sa”。))

0.5.4

  • 允许将 uuid_format(允许“十六进制”(默认)或“字符串”)传递到 UUID 字段以更改其保存格式。默认情况下,字段以十六进制格式保存(修剪为 32 个字符(不带破折号)),但您可以传递 format='string' 以使用 36 (带破折号)来调整现有数据库或其他库。

    样本:

    • 十六进制值 = c616ab438cce49dbbf4380d109251dce
    • 字符串值 = c616ab43-8cce-49db-bf43-80d109251dce

0.5.3

  • 修复了 Model.model_dump() 方法中忽略排除参数且不包含字典参数的错误。

0.5.2

  • 添加了 prefetch_lated 方法以在单独的查询中加载后续模型。
  • 更新文档

0.5.1

  • 切换到 github actions 而不是 travis
  • 更新文档中的徽章

0.5.0

  • 添加了保存状态 -> 您可以检查模型是否已使用 ModelInstance.saved 属性保存
    • 在模型上保存/更新/加载/更新插入方法后保存模型
    • 模型保存后 create/get/first/all/get_or_create/update_or_create 方法
    • 模型在传递给bulk_update和bulk_create时被保存
    • 添加/删除ManyToMany相关对象后保存模型(通过模型实例自动保存/删除)
    • 更改任何自己的字段后不会保存模型(包括作为 Model.pk 别名的 pk)
    • 添加/删除ForeignKey相关对象后模型未保存(fk列未保存)
    • 使用 __init__ 实例化后不保存模型(不使用 QuerySet.create 或调用 save 之前)
  • 添加了 Model.upsert(**kwargs),如果 pk 未设置,则执行 save(),否则 update(**kwargs)
  • 额外 Model.save_related(follow=False) 迭代所有关系中的所有相关对象并检查它们是否已保存。如果不是,它会对每个对象调用 upsert() 。
  • 破坏:如果添加/删除未保存(pk 为 None)模型到多对多关系,则添加引发异常
  • 允许将字典和集合传递给 fields 和 except_fields
  • 自动将 str 和列表翻译为字段和 except_fields 的字典
  • 破坏:将嵌套模型传递给 fields 和 excre_fields 现在是通过相关的外键名称而不是目标模型名称
  • 性能优化 - 在 modelproxy、newbasemodel 中 - 查询减少 >,某些属性缓存在模型上
  • 清理未使用的关系代码
  • 添加可选的性能依赖项orjson(强烈推荐)
  • 更新文档

0.4.4

  • 添加 except_fields() 方法以从 sql 中排除字段
  • 重构列名称设置(别名)
  • 修复带有别名的列的排序方式
  • 对 fields 和 except_fields 的附加测试
  • 更新文档

0.4.3

  • 包含 models.model_dump() 和 model.model_dump_json() 中的属性

0.4.2

  • 修改 pydantic 模型的创建以允许返回仅填充 pk 的相关模型

0.4.1

  • 将 order_by 方法添加到查询集中以允许排序
  • 更新文档

0.4.0

  • 更改了模型定义中的符号 -> 现在使用 name = ormar.Field() 而不是 name: ormar.Field()
    • 请注意,旧的表示法仍然受支持,但已弃用,并且无法与 mypy 和 pydantic pycharm 插件等静态检查器很好地配合
  • 输入提示文档并测试
  • 也不能使用 mypy 进行测试,只能使用 ormar 包
  • 使用 max_digits 和decimal_places pydantic Decimal 字段修复比例和精度转换
  • 更新文档 - 添加依赖项的最佳实践
  • 重构元类和 model_fields 以更好地使用类型提示
  • 将 mypy 和 pydantic 插件添加到文档中
  • 展开有关多对多关系的文档

0.3.11

  • 修复将 server_default 设置为 python 中的默认字段值

0.3.10

  • 修复 postgresql 检查以避免使用不同后端时未安装驱动程序的异常

0.3.9

  • 从 #19 开始修复 json 模式生成
  • 修复了 ormar.Models 的 fastapi 副本中未初始化的 ManyToMany 关系的问题
  • 更新有关 fastapi 使用的文档
  • 添加测试以验证 fastapi/docs 正确生成

0.3.8

  • 添加了为所有字段提供带有名称参数的替代数据库列名称的可能性。
  • 修复使用 fields() 选择相关 ManyToMany 字段(如果它们为空)的错误。
  • 更新文档

0.3.7

  • 发布文档并更新自述文件

0.3.6

  • 添加 fields() 方法来限制数据库中选定的列 - 只能排除可为空的列。
  • 在模型元中添加了 UniqueColumns 和约束列表,以在列列表上构建唯一约束。
  • 添加了基于 Char(32) 列类型的 UUID 字段类型。

0.3.5

  • 添加了针对多个对象的操作的bulk_create和bulk_update。

0.3.4

添加查询集级别方法

  • 删除
  • 更新
  • 获取或创建
  • 更新或创建

0.3.3

  • 添加额外的过滤器 - 开头和结尾

0.3.2

  • 将选项参数添加到所有字段 - 将接受的值限制为提供的值

0.3.1

  • 添加了排除来过滤 where not 条件。
  • 添加了针对 mysql 和 postgres 的测试,并修复了 postgres。
  • Rafactors 和清理。

0.3.0

  • 添加了 ManyToMany 字段并支持多对多关系