bc291
bc291

Reputation: 1171

Hot to get all items from sqlalchemy_mptt Tree

I'm using sqlalchemy_mptt to create tree structure. My models are defined as follows:

class TreeGroup(BaseNestedSets, db.Model):
    name = db.Column(db.String(400), index=True, unique=True)
    note = db.Column(db.Text(), nullable=True)
    items = db.relationship("Item", backref='item', lazy='dynamic')

    def __init__(self, name, parent_id=None):
        self.uuid = uuid4().hex
        self.name = name
        self.parent_id = parent_id
    def __repr__(self):
        return '{}'.format(self.name)

class Item(db.Model):
    __tablename__ = 'items'
    id = db.Column(db.Integer, primary_key=True)
    category_id = db.Column(db.Integer, db.ForeignKey('tree_groups.id'))
    name = db.Column(db.String(475), index=True)

Inserted dummy data:

db.session.add(TreeGroup(name="Root"))  # root node
    db.session.add_all(  # second level
    [
        TreeGroup(name="Test2", parent_id=1),  # id=2
        TreeGroup(name="Test3", parent_id=1),  # id=3
        TreeGroup(name="Test4", parent_id=1),  # id=4
    ]
    )
    db.session.add_all(  # third level
    [
        TreeGroup(name="Test5", parent_id=2),  # id=5
        TreeGroup(name="Test6", parent_id=2),  # id=6
        TreeGroup(name="Test7", parent_id=3),  # id=7
        TreeGroup(name="Test8", parent_id=3),  # id=8
        TreeGroup(name="Test9", parent_id=4),  # id=9
        TreeGroup(name="Test10", parent_id=4)  # id=10
    ]
    )

    db.session.add_all(  # fourth level
    [
        TreeGroup(name="Test11", parent_id=5),
        TreeGroup(name="Test12", parent_id=5),
        TreeGroup(name="Test13", parent_id=6),
        TreeGroup(name="Test14", parent_id=7)
    ]
    )

    db.session.commit()

Let's focus now on node with id=3 ("Test3 node"). I would like to view all its items, and items below him. (from children: Test7 node and Test8 node as well as their childer (Test7) -> Test14.

How can i achieve this? I thought about: - recursive - maybe some tricky sqlalchemy joins

I know also that children can be obtained via:

x = TreeGroup.query.filter_by(name=group_name).first()
children = x.drilldown_tree() #but will that help me?

Upvotes: 2

Views: 452

Answers (1)

Danila Ganchar
Danila Ganchar

Reputation: 11312

You are right - you can use drilldown_tree() + recursion. Here is example:

def print_tree(group_name, tab=1):
    """
    :param str group_name: 
    :param int tab: used just for formatting
    """
    group = TreeGroup.query.filter_by(name=group_name).one_or_none()  # type: TreeGroup
    if not group:
        return
    # group found - print name and find children 
    print('- ' * tab + group.name)
    for child_group in group.children:  # type: TreeGroup
        # new tabulation value for child record
        print_tree(child_group.name, tab * 2)

Examples:

# print_tree('Test3')
- Test3
- - Test7
- - - - Test14
- - Test8
# print_tree('Test2')
- Test2
- - Test5
- - - - Test11
- - - - Test12
- - Test6
- - - - Test13

Hope this helps.

Upvotes: 2

Related Questions