如何在SQLAlchemy column_property上创建索引?

问题描述 投票:0回答:1

使用SQLAlchemy和SQLite引擎,我有一个描述目录结构的自引用层次表。

from sqlalchemy import Column, Integer, String, ForeignKey, Index
from sqlalchemy.orm import column_property, aliased, join
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class Dr(Base):
    __tablename__ = 'directories'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    parent_id = Column(Integer, ForeignKey('directories.id'))

每个Dr行只知道它自己的“名称”及其“parent_id”。我添加了一个名为“path”的递归column_property,它返回一个字符串,其中包含来自根博士的所有Dr的祖先。

root_anchor = (
    select([Dr.id, Dr.name, Dr.parent_id,Dr.name.label('path')])
    .where(Dr.parent_id == None).cte(recursive=True)
)

dir_alias = aliased(Dr)
cte_alias = aliased(root_anchor)

path_table = root_anchor.union_all(
    select([
        dir_alias.id, dir_alias.name,
        dir_alias.parent_id, cte_alias.c.path + "/" + dir_alias.name
    ]).select_from(join(
        dir_alias, cte_alias, onclause=cte_alias.c.id==dir_alias.parent_id)
    ))
)

Dr.path = column_property(
    select([path_table.c.path]).where(path_table.c.id==Dr.id)
)

这是输出的一个例子:

"""
-----------------------------
| id |   name   | parent_id |
-----------------------------
|  1 | root     | NULL      |
-----------------------------
|  2 | kid      | 1         |
-----------------------------
|  3 | grandkid | 2         |
-----------------------------
"""
sqllite_engine = create_engine('sqlite:///:memory:')
Session = sessionmaker(bind=sqllite_engine)
session = Session()

instance = session.query(Dr).filter(Dr.name=='grandkid').one()
print(instance.path)
# Outputs: "root/kid/grandkid" 

我希望能够在“path”属性上添加索引或至少一个唯一约束,以便在表中不能存在多个唯一路径。我试过了:

Index('pathindex', Directory.path, unique=True)

......没有运气。没有引发错误,但SQLAlchemy似乎没有注册索引,它只是默默地忽略它。它仍然允许添加重复路径,例如:

session.add(Dr(name='grandkid', parent_id=2))
session.commit()

作为忽略Index()的进一步证据,检查表的“indexes”属性会导致一个空集:

print(Dr.__table__.indexes)
#Outputs: set([])

对我来说,重要的路径不能存在于数据库中是至关重要的。我不确定在SQLAlchemy中我是否可以尝试使用column_property,如果不是,我很想听听关于我如何能够解决这个问题的一些建议。

python sql sqlite sqlalchemy flask-sqlalchemy
1个回答
1
投票

我认为独特的指数应该足够了,在课堂上Db

__table_args__ = (UniqueConstraint('parent_id', 'name'), )
© www.soinside.com 2019 - 2024. All rights reserved.