Python 查找sqlalchemy orm中的根引用

Python 查找sqlalchemy orm中的根引用,python,sqlalchemy,Python,Sqlalchemy,有一个模型具有自引用关系,我想找出引用的根节点/记录,例如在下面的示例中,包可能依赖于另一个包 # myapp.py from flask import Flask from flask_sqlalchemy import SQLAlchemy from sqlalchemy.orm import relationship app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db

有一个模型具有自引用关系,我想找出引用的根节点/记录,例如在下面的示例中,包可能依赖于另一个包

# myapp.py

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.orm import relationship

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
db = SQLAlchemy(app)


class Package(db.Model):
    __tablename__ = "packages"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(80), unique=True)
    dep_on_id = db.Column(db.Integer, db.ForeignKey('packages.id'))
    dep_on = relationship('Package', remote_side=[id])

    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return '<Package (%r)>' % self.name

遍历树和图形可以在SQL中使用,也可以在SQLAlchemy中完成

def find_root_dep(package):
    # The initial step. Find the 1st dependency of the Package passed
    # as the argument.
    cte = db.session.query(Package).\
        filter_by(id=package.dep_on_id).\
        cte(recursive=True)

    # The iterative step. Find Packages that found packages
    # depend on. Iteration stops when the query results in
    # an empty set, since no Package has NULL id.
    cte = cte.union_all(
        db.session.query(Package).
            filter_by(id=cte.c.dep_on_id))

    # Create an alias for returning an entity object.                
    result_alias = db.aliased(Package, cte)

    # The root depends on nothing.        
    return db.session.query(result_alias).\
        filter_by(dep_on_id=None).\
        one_or_none()
如果传递一个根包,您的原始实现将返回None,因此SQL实现直接通过查找第一个依赖项开始,这将导致根包的集合为空。

您可能需要设备a来查找根。
def find_root_dep(package):
    # The initial step. Find the 1st dependency of the Package passed
    # as the argument.
    cte = db.session.query(Package).\
        filter_by(id=package.dep_on_id).\
        cte(recursive=True)

    # The iterative step. Find Packages that found packages
    # depend on. Iteration stops when the query results in
    # an empty set, since no Package has NULL id.
    cte = cte.union_all(
        db.session.query(Package).
            filter_by(id=cte.c.dep_on_id))

    # Create an alias for returning an entity object.                
    result_alias = db.aliased(Package, cte)

    # The root depends on nothing.        
    return db.session.query(result_alias).\
        filter_by(dep_on_id=None).\
        one_or_none()