声明式SQLAlchemy中的物化路径关系
我有一个分层的分类模型,层级是通过一种叫做“物化路径”的方式来维护的(每一层用一个字符表示):
class Category(Base):
__tablename__ = 'categories'
id = Column(SmallInteger, primary_key=True)
path = Column(String, unique=True, nullable=False)
# problematic relationship
all_subcats = relationship('Category', lazy='dynamic', viewonly=True,
primaryjoin=foreign(path).like(remote(path).concat('%')))
在尝试定义“所有子分类”关系时,我遇到了一个问题:
sqlalchemy.exc.ArgumentError: Can't determine relationship direction for
relationship 'Category.all_subcats' - foreign key columns within the join
condition are present in both the parent and the child's mapped tables.
Ensure that only those columns referring to a parent column are marked as
foreign, either via the foreign() annotation or via the foreign_keys argument.
SQLAlchemy感到困惑,因为我是在同一列上进行连接。所有我找到的例子都是在不同的列上进行连接。
这种关系到底有没有可能?我想通过这个连接来查询,所以自定义的@property是不行的。
1 个回答
2
使用最新的git主分支或者版本号在0.9.5及以上的SQLAlchemy。然后:
from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Element(Base):
__tablename__ = 'element'
path = Column(String, primary_key=True)
related = relationship('Element',
primaryjoin=
remote(foreign(path)).like(
path.concat('/%')),
viewonly=True,
order_by=path)
e = create_engine("sqlite://", echo=True)
Base.metadata.create_all(e)
sess = Session(e)
sess.add_all([
Element(path="/foo"),
Element(path="/foo/bar1"),
Element(path="/foo/bar2"),
Element(path="/foo/bar2/bat1"),
Element(path="/foo/bar2/bat2"),
Element(path="/foo/bar3"),
Element(path="/bar"),
Element(path="/bar/bat1")
])
e1 = sess.query(Element).filter_by(path="/foo/bar2").first()
print [e.path for e in e1.related]
请注意,这个模型无论你处理的是“子类”还是“父类”,都使用了集合。你需要把remote()
和foreign()
放在一起,这样ORM(对象关系映射)才能把它们看作是一对多的关系。