排序列表


一个自定义列表,用于管理包含元素的索引/位置信息。


作者


杰森·嘉德兰


OrderingList 是可变有序关系的帮助程序。它将拦截对 relationship() 管理的集合执行的列表作,并自动将列表位置的更改同步到目标标量属性上。


示例:幻灯片表,其中每行引用相关项目符号表中的零个或多个条目。幻灯片中的项目符号根据 position 列的值按顺序显示 Bullet 表。 当条目在内存中重新排序时, 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)


标准关系映射将在每个 包含所有相关 Bullet 对象的幻灯片,但不会自动处理顺序的变化。将 Bullet 附加到 Slide.bullets 中时,Bullet.position 属性将保持未设置状态,直到手动分配。 当 Bullet 插入到列表的中间,则还需要对以下 Bullet 对象重新编号。


OrderingList 对象自动执行此任务,管理 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 构造仅适用于对集合的更改,而不适用于从数据库进行的初始加载,并且要求在加载时对列表进行排序。因此,order_by请务必在 relationship() 来验证 TARGET Ordering 属性,以便在首次加载时排序是正确的。


警告


OrderingList 仅在主键列或唯一列是排序的目标时提供有限的功能。不受支持或有问题的作包括:


  • 两个条目必须交易价值。在主键或唯一约束的情况下,不直接支持这样做,因为这意味着在切换发生时,至少需要先暂时删除一行,或者更改为第三个中性值。


  • 必须删除条目才能为新条目腾出空间。SQLAlchemy 的工作单元在一次刷新中执行 DELETE 之前的所有 INSERT。对于主键,它会将同一主键的 INSERT/DELETE 换成 UPDATE 语句,以减少此限制的影响,但对于 UNIQUE 列,则不会发生这种情况。未来的功能将允许“DELETE before INSERT”行为成为可能,从而减轻了这一限制,尽管此功能将需要在映射器级别对要以这种方式处理的列集进行显式配置。


ordering_list() 将相关对象的 ordering 属性的名称作为参数。默认情况下,对象在 ordering_list() 中位置的从零开始的整数索引与 ordering 属性同步:索引 0 将获得位置 0,索引 1 将获得位置 1,依此类推。要从 1 或其他整数开始编号,请提供 count_from=1


API 参考


对象名称

描述


count_from_0(索引、集合)


编号功能:从 0 开始的连续整数。


count_from_1(索引、集合)


编号功能:从 1 开始的连续整数。


count_from_n_factory(开始)


编号功能:从任意起点开始的连续整数。


ordering_list(attr[, count_from, ordering_func, reorder_on_append])


准备一个 OrderingList 工厂以用于 Mapper 定义。


订购清单


一个自定义列表,用于管理其子项的位置信息。


函数 sqlalchemy.ext.orderinglist 中。ordering_listattrstr count_from:intNone=None, ordering_func:Callable[[int,Sequence[_T]],int]None=None, reorder_on_append: bool = False 可调用[[] 订购列表]


准备一个 OrderingList 工厂以用于 Mapper 定义。


返回一个适合用作 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"),
    )

参数

  • attr– 用于存储和检索订购信息的映射属性的名称


  • count_from– 设置基于整数的排序,从 count_from 开始。例如, ordering_list('pos', count_from=1) 将创建一个从 1 开始的 list 的 SQL 中,将值存储在 'pos' 列中。 如果 Ignored ordering_func 已提供。


其他参数将传递给 OrderingList 构造函数。


函数 sqlalchemy.ext.orderinglist 中。count_from_0indexcollection


编号功能:从 0 开始的连续整数。


函数 sqlalchemy.ext.orderinglist 中。count_from_1indexcollection


编号功能:从 1 开始的连续整数。


函数 sqlalchemy.ext.orderinglist 中。count_from_n_factorystart


编号功能:从任意起点开始的连续整数。


sqlalchemy.ext.orderinglist 中。排序列表


一个自定义列表,用于管理其子项的位置信息。


OrderingList 对象通常使用 ordering_list() 工厂函数,与 relationship() 函数结合使用。


类签名


class sqlalchemy.ext.orderinglist.OrderingList builtins.listtyping.通用


方法 sqlalchemy.ext.orderinglist.OrderingList. __init__ordering_attr:strNone=None, ordering_func:Callable[[int,Sequence[_T]],int]None=None, reorder_on_append: bool = False


一个自定义列表,用于管理其子项的位置信息。


OrderingList 是一个 collection_class 列表实现,它将 Python 列表中的 position 与 Map 对象上的 position 属性同步。


此实现依赖于以正确的顺序开始的列表,因此请务必对你的关系进行order_by


参数

  • ordering_attr– 在关系中存储对象顺序的属性的名称。

  • ordering_func


    自选。 一个函数,该函数将 将 Python 列表转换为要存储在 ordering_attr。返回的值通常是(但不一定是)整数。


    使用两个位置参数调用 ordering_func:列表中元素的索引和列表本身。


    如果省略,则 Python 列表索引将用于属性值。 本模块提供了两个基本的预构建编号功能: count_from_0count_from_1。有关更多奇特的示例,如阶梯编号、字母顺序和斐波那契编号,请参阅单元测试。

  • reorder_on_append


    默认为 False。 当附加具有现有 (non-None) 的对象时 ordering 值,该值将保持不变,除非 reorder_on_append是真的。这是一种优化,可避免各种危险的意外数据库写入。


    SQLAlchemy 将在对象加载时通过 append() 将实例添加到列表中。如果由于某种原因,数据库中的结果集跳过了排序中的一个步骤(例如,缺少行 '1',但您得到了 '2'、'3' 和 '4'),reorder_on_append=True 会立即将项目重新编号为 '1'、'2'、'3'。如果你有多个会话进行更改,其中任何一个会话碰巧加载了这个集合,即使顺便加载了这个集合,所有会话都会尝试 “清理” 其提交中的编号,这可能会导致除一个会话之外的所有会话都失败并出现并发修改错误。


    建议将其保留为默认值 False,然后调用 reorder() 如果你正在对以前排序的实例进行 append()作,或者在手动 SQL作后进行一些内务处理。


方法 sqlalchemy.ext.orderinglist.OrderingList. appendentity


将 object 附加到列表的末尾。


方法 sqlalchemy.ext.orderinglist.OrderingList. insertindexentity


在索引之前插入对象。


方法 sqlalchemy.ext.orderinglist.OrderingList. popindex=-1


删除并返回 index 处的项目(默认为 last)。


如果 list 为空或 index 超出范围,则引发 IndexError 。


方法 sqlalchemy.ext.orderinglist.OrderingList. removeentity


删除第一个出现的值。


如果值不存在,则引发 ValueError。


方法 sqlalchemy.ext.orderinglist.OrderingList. reorder


同步整个集合的排序。


扫描列表并确保每个对象都设置了准确的排序信息。