Python 声明式SQLAlchemy中的物化路径关系
我有一个层次分类模型,其中使用物化路径(每层一个字符)维护层次结构: 在尝试定义“所有子类别”关系时,我遇到了一个问题:Python 声明式SQLAlchemy中的物化路径关系,python,sqlalchemy,relationship,declarative,materialized-path-pattern,Python,Sqlalchemy,Relationship,Declarative,Materialized Path Pattern,我有一个层次分类模型,其中使用物化路径(每层一个字符)维护层次结构: 在尝试定义“所有子类别”关系时,我遇到了一个问题: 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 a
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是不可接受的。请使用最新的git master或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将其视为一对多。您应该在上报告类似的问题。我现在正在测试一个补丁。哇,这真是太奇怪了。需要看看我是否可以提交这个。它与SQLAlchemy git master配合使用很好。非常感谢!有没有这样的方法可以在不为每个对象发出单独的SELECT的情况下加载子查询?如果使用subqueryload(),会发生什么情况?它失败了?在这种情况下可能需要更多的修复,发布错误报告。@zzzeek-Hm,似乎subqueryload()
可以工作,但指定lazy=“subquery”
则不行。我将提交一份错误报告。
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]