Search code examples
pythonjsonflaskflask-sqlalchemyflask-restful

How to create a json tree structure from SQLalchemy model


I'm trying to create a webservice with Flask, my webservice needs to return a json encoded tree structure of all activities belonging to a profile.

My models:

class Activity(db.Model):
    __tablename__ = 'activity'
    id = db.Column(db.Integer, primary_key=True)
    profile_id = db.Column(db.String, db.ForeignKey('profile.id'), nullable=False, index=True)
    parent_id = db.Column(db.Integer, db.ForeignKey('activity.id'), index=True)
    name = db.Column(db.String)

    parent = db.relationship('Activiteit', remote_side=[id], backref='children')

class Profile(db.Model):
    __tablename__ = 'profile'
    id = db.Column(db.Integer, primary_key=True)
    profile_name = db.Column(db.String(64))
    active = db.Column(db.Boolean, nullable=False)

    activities = db.relationship('Activity', backref="profile", lazy='dynamic')
    employees = db.relationship('Employee', backref="profile", lazy='dynamic')

I need the following structure:

Main activity 1
     Sub activity 1
     Sub activity 2
         Subsub activity 1
Main activity 2
etc. etc.

I tried creating nested dicts and lists of dicts, but everytime I get stuck. Level 3 elements that end up as Level 1 elements or a tree that only returns 2 levels.

After some searching I found that I need to create a Queue with Nodes that carry a name and a list of children and then add the Nodes to the tree.

I created the Queue with the following function:

def get(self, profile_id):
    profile = models.Profile.query.get(profile_id)
    queue = {}
    for activity in profile.activities:
        queue[activity.name]= [c.name for c in activity.children]

Now I have no clue how to proceed or if i'm even on the right way. Any help will be much appreciated

Edit

Based on Codegeek's answer I create the following:

def get(self, profile_id):
    activities = models.Activity.query.filter_by(profile_id=profile_id).all()
    tree = {}
    for level1 in activities:
        if level1.parent_id is None:
            tree[level1.name] = {'id': level1.id}
            for level2 in level1.children:
                tree[level1.name][level2.name] = {'id': level2.id}
                for level3 in level2.children:
                    tree[level1.name][level2.name][level3.name] = {'id': level3.id}
    return tree

Solution

  • Have you tried using flask.jsonify() ?

    jsonify() takes dictionary as argument. You can try creating a nested dictionary. In your case, it is 3 levels and could look like:

    d= { 'Activity': { 'Subactivity': { 'Subsubactivity': 'value }}}
    

    You have not shared your code where you create the dictionary but you can do something like below (I am using generic names of course)

    d = {}
    for activity in Activities:
        for subactivity in activity:
            for subsubactivity in subactivity:
                d['Activity']['Subactivity']['subsubactivity'] = value
    

    Then you can reuturn the JSON as:

    return flask.jsonify(**d)