SQLAlchemy 2.0 文档
排序列表¶
一个自定义列表,用于管理包含元素的索引/位置信息。
- 作者:
Jason Kirtland
orderinglist
是用于可变有序关系的助手。它将拦截在 relationship()
-管理的集合上执行的列表操作,并自动将列表位置的更改同步到目标标量属性。
示例:一个 slide
表,其中每一行引用相关 bullet
表中的零个或多个条目。幻灯片中的项目符号根据 bullet
表中 position
列的值按顺序显示。当在内存中重新排序条目时,应更新 position
属性的值以反映新的排序顺序
Base = declarative_base()
class Slide(Base):
__tablename__ = "slide"
id = Column(Integer, primary_key=True)
name = Column(String)
bullets = relationship("Bullet", order_by="Bullet.position")
class Bullet(Base):
__tablename__ = "bullet"
id = Column(Integer, primary_key=True)
slide_id = Column(Integer, ForeignKey("slide.id"))
position = Column(Integer)
text = Column(String)
标准关系映射将在每个 Slide
上生成一个类似列表的属性,其中包含所有相关的 Bullet
对象,但自动处理排序中的更改。当将 Bullet
附加到 Slide.bullets
中时,Bullet.position
属性将保持未设置状态,直到手动分配为止。当 Bullet
插入到列表的中间时,还需要重新编号以下 Bullet
对象。
OrderingList
对象自动执行此任务,管理集合中所有 Bullet
对象的 position
属性。它使用 ordering_list()
工厂构造
from sqlalchemy.ext.orderinglist import ordering_list
Base = declarative_base()
class Slide(Base):
__tablename__ = "slide"
id = Column(Integer, primary_key=True)
name = Column(String)
bullets = relationship(
"Bullet",
order_by="Bullet.position",
collection_class=ordering_list("position"),
)
class Bullet(Base):
__tablename__ = "bullet"
id = Column(Integer, primary_key=True)
slide_id = Column(Integer, ForeignKey("slide.id"))
position = Column(Integer)
text = Column(String)
使用上述映射,Bullet.position
属性被管理
s = Slide()
s.bullets.append(Bullet())
s.bullets.append(Bullet())
s.bullets[1].position
>>> 1
s.bullets.insert(1, Bullet())
s.bullets[2].position
>>> 2
OrderingList
构造仅适用于集合的更改,而不适用于从数据库的初始加载,并且要求在加载时对列表进行排序。因此,请务必在针对目标排序属性的 relationship()
上指定 order_by
,以便在首次加载时排序正确。
警告
当主键列或唯一列是排序的目标时,OrderingList
仅提供有限的功能。不受支持或存在问题的操作包括
两个条目必须交换值。在主键或唯一约束的情况下,这不被直接支持,因为这意味着至少需要先临时删除一个行,或者在交换发生时更改为第三个中性值。
必须删除一个条目才能为新条目腾出空间。SQLAlchemy 的工作单元在单个刷新中先执行所有 INSERT,然后再执行 DELETE。在主键的情况下,它将交换相同主键的 INSERT/DELETE 以进行 UPDATE 语句,以减少此限制的影响,但这不会发生在 UNIQUE 列上。未来的功能将允许“先 DELETE 后 INSERT”的行为成为可能,从而缓解此限制,尽管此功能将需要在映射器级别显式配置要以这种方式处理的列集。
ordering_list()
将相关对象的排序属性的名称作为参数。默认情况下,ordering_list()
中对象位置的从零开始的整数索引与排序属性同步:索引 0 将获得位置 0,索引 1 位置 1,依此类推。要从 1 或其他整数开始编号,请提供 count_from=1
。
API 参考¶
对象名称 | 描述 |
---|---|
count_from_0(index, collection) |
编号函数:从 0 开始的连续整数。 |
count_from_1(index, collection) |
编号函数:从 1 开始的连续整数。 |
count_from_n_factory(start) |
编号函数:从任意 start 开始的连续整数。 |
ordering_list(attr[, count_from, ordering_func, reorder_on_append]) |
准备 |
一个自定义列表,用于管理其子项的位置信息。 |
- function sqlalchemy.ext.orderinglist.ordering_list(attr: str, count_from: int | None = None, ordering_func: Callable[[int, Sequence[_T]], int] | None = None, reorder_on_append: bool = False) → Callable[[], OrderingList]¶
准备
OrderingList
工厂以用于映射器定义。返回一个适合用作 Mapper 关系的
collection_class
选项的参数的对象。例如:from sqlalchemy.ext.orderinglist import ordering_list class Slide(Base): __tablename__ = "slide" id = Column(Integer, primary_key=True) name = Column(String) bullets = relationship( "Bullet", order_by="Bullet.position", collection_class=ordering_list("position"), )
- 参数:
其他参数将传递给
OrderingList
构造函数。
- function sqlalchemy.ext.orderinglist.count_from_0(index, collection)¶
编号函数:从 0 开始的连续整数。
- function sqlalchemy.ext.orderinglist.count_from_1(index, collection)¶
编号函数:从 1 开始的连续整数。
- function sqlalchemy.ext.orderinglist.count_from_n_factory(start)¶
编号函数:从任意 start 开始的连续整数。
- class sqlalchemy.ext.orderinglist.OrderingList¶
一个自定义列表,用于管理其子项的位置信息。
OrderingList
对象通常使用ordering_list()
工厂函数设置,与relationship()
函数结合使用。类签名
class
sqlalchemy.ext.orderinglist.OrderingList
(builtins.list
,typing.Generic
)-
method
sqlalchemy.ext.orderinglist.OrderingList.
__init__(ordering_attr: str | None = None, ordering_func: Callable[[int, Sequence[_T]], int] | None = None, reorder_on_append: bool = False)¶ 一个自定义列表,用于管理其子项的位置信息。
OrderingList
是一个collection_class
列表实现,它将 Python 列表中的位置与映射对象上的位置属性同步。此实现依赖于列表以正确的顺序启动,因此请确保在关系上放置
order_by
。- 参数:
ordering_attr¶ – 存储对象在关系中顺序的属性名称。
ordering_func¶ –
可选。一个函数,用于将 Python 列表中的位置映射到要存储在
ordering_attr
中的值。返回的值通常(但不一定!)是整数。ordering_func
在调用时带有两个位置参数:元素在列表中的索引和列表本身。如果省略,则 Python 列表索引将用于属性值。此模块中提供了两个基本的预构建编号函数:
count_from_0
和count_from_1
。有关更奇特的示例,如步进编号、字母编号和斐波那契编号,请参阅单元测试。reorder_on_append¶ –
默认为 False。当附加具有现有(非 None)排序值的对象时,除非
reorder_on_append
为 true,否则该值将保持不变。这是一种优化,可以避免各种危险的意外数据库写入。当您的对象加载时,SQLAlchemy 将通过 append() 将实例添加到列表中。如果由于某种原因数据库的结果集跳过了排序中的一个步骤(例如,行 '1' 丢失,但您得到 '2'、'3' 和 '4'),则 reorder_on_append=True 将立即将项目重新编号为 '1'、'2'、'3'。如果您有多个会话进行更改,其中任何一个会话碰巧加载了这个集合,即使只是路过,所有会话都会尝试在其提交中“清理”编号,可能会导致除一个会话外的所有会话都因并发修改错误而失败。
建议将此项保留为默认值 False,并且如果您使用先前排序的实例执行
append()
操作,或者在手动 sql 操作后执行一些内务处理时,只需调用reorder()
。
-
method
sqlalchemy.ext.orderinglist.OrderingList.
append(entity)¶ 将对象附加到列表的末尾。
-
method
sqlalchemy.ext.orderinglist.OrderingList.
insert(index, entity)¶ 在索引之前插入对象。
-
method
sqlalchemy.ext.orderinglist.OrderingList.
pop(index=-1)¶ 删除并返回索引处的项(默认为最后一个)。
如果列表为空或索引超出范围,则引发 IndexError。
-
method
sqlalchemy.ext.orderinglist.OrderingList.
remove(entity)¶ 删除值的首次出现。
如果值不存在,则引发 ValueError。
-
method
sqlalchemy.ext.orderinglist.OrderingList.
reorder() → None¶ 同步整个集合的排序。
扫描列表并确保每个对象都设置了准确的排序信息。
-
method
flambé! 龙和 炼金术士 图像设计由 Rotem Yaari 创建并慷慨捐赠。
使用 Sphinx 7.2.6 创建。文档最后生成时间:2025 年 3 月 11 日星期二下午 02:40:17 EDT