Find out the root reference in sqlalchemy orm

Viewed 351

There is a model has self-referential relationship, I want to find out the root node/record of the reference, for example in the following example, Package may depends on another package.

# 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

If package D depends on C, C depends on B, B depends on A, I want to find out the root depend package of D, which is A, So the expect result in the follwing test code should be <Package (u'a')>, is there an easy approach I can do with sqlalchemy to replace the find_root_dep function?

# test.py

from myapp import db, Package

db.drop_all()
db.create_all()

a = Package('a')
b = Package('b')
c = Package('c')
d = Package('d')
b.dep_on = a
c.dep_on = b
d.dep_on = c

for p in [a, b, c, d]:
    db.session.add(p)
db.session.commit()

def find_root_dep(package):
    dep_on = package.dep_on
    while dep_on:
        dep = dep_on.dep_on
        if dep:
            dep_on = dep
        else:
            break
    return dep_on

print find_root_dep(d)
1 Answers
Related