Constructing hierarchy from dictionary/JSON

2024/10/5 5:11:53

I'm looking for a way to create hierarchy in form of child parent relationship between two or more instances of same class.

How would one go about creating such objects from nested dictionary like in example ? Is this even possible ? Is there some other way which would be recommended to do such task?

# -*- coding: utf-8 -*-from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import create_engine, exists
from sqlalchemy.orm import relationship, sessionmaker
from sqlalchemy.schema import Column, ForeignKey
from sqlalchemy.types import Integer, StringBase = declarative_base()class Person(Base):__tablename__ = 'person';id = Column(Integer, primary_key=True)name = Column(String, nullable=False)parent_id = Column(Integer, ForeignKey('person.id'))def __init__(self, **kwargs):self.parent_id = kwargs.get('parent_id', None)self.name = kwargs.get('name')self.team = kwargs.get('team', [])# Is it possible to create more object of this type# and establish that their parent_id is ID of this object?def __repr__(self):return """ID: {}Name: {}ParentID: {}""".format(self.id, self.name, self.parent_id)engine = create_engine('sqlite:///db.sqlite3')
Base.metadata.create_all(engine)
connection = engine.connect()
Session = sessionmaker(bind=engine)
session = Session()alice = {'name' : 'Alice'}
bob = {'name' : 'Bob', 'team' : [alice, ]}p1 = Person(bob)
session.add(p1)
session.commit()

I understand the iterative approach where I would first create parent object, then iterate over possible children and create them. I'm curious if there is a way to do this inside constructor rather than from 'outside' with loops.

Answer

Try this.

#your import statements including "relationship"Base = declarative_base()class Person(Base):__tablename__ = 'person'id = Column(Integer, primary_key=True)name = Column(String, nullable=False)parent_id = Column(Integer, ForeignKey('person.id'))team = relationship("Person")  def __init__(self, **kwargs):self.parent_id = kwargs.get('parent_id', None)self.name = kwargs.get('name')team_kwargs = kwargs.get('team', [])for member_kwargs in team_kwargs:new_person = Person(**member_kwargs)new_person.parent_id = self.idself.team.append(new_person)# Is it possible to create more object of this type# and establish that their parent_id is ID of this object?def __repr__(self):return """ID: {}Name: {}ParentID: {}""".format(self.id, self.name, self.parent_id)engine = create_engine('sqlite://')
Base.metadata.create_all(engine)
connection = engine.connect()
Session = sessionmaker(bind=engine)
session = Session()alice = {'name' : 'Alice'}
joe = {'name' : 'Joe'}
anne = {'name' : 'Anne', 'team': [alice]}
bob = {'name' : 'Bob', 'team' : [anne, joe]}p1 = Person(**bob) session.add(p1)   
session.commit()for person in session.query(Person).all():print(person)

output:

    ID: 1Name: BobParentID: NoneID: 2Name: AnneParentID: 1ID: 3Name: JoeParentID: 1ID: 4Name: AliceParentID: 2

when i ran this on a saved database, (engine = create_engine('sqlite:///delme.db'), and ran it multiple times, it created all the entries on a single add and commit.

Different Approach

You could also make a separate "teams" table that stores team leader and team members

# your imports and "from sqlalchemy import create_engine, Table"Base = declarative_base()teams = Table("teams", Base.metadata,Column("leader", Integer, ForeignKey("person.id"), primary_key=True),Column("member", Integer, ForeignKey("person.id"), primary_key=True),)class Person(Base):__tablename__ = 'person'id = Column(Integer, primary_key=True)name = Column(String, nullable=False)team = relationship("Person",secondary=teams,primaryjoin=id==teams.c.leader,secondaryjoin=id==teams.c.member,)def __init__(self, **kwargs):self.name = kwargs.get('name')team_input = kwargs.get('team', [])for member in team_input:new_person = Person(**member)self.team.append(new_person)def __repr__(self):return "ID: {}  Name: {}".format(self.id, self.name)engine = create_engine('sqlite://')
Base.metadata.create_all(engine)
connection = engine.connect()
Session = sessionmaker(bind=engine)
session = Session()alice = {'name' : 'Alice'}
joe = {'name' : 'Joe'}
anne = {'name' : 'Anne', 'team': [alice]}
bob = {'name' : 'Bob', 'team' : [anne, joe]}p1 = Person(**bob)
session.add(p1)
session.commit()for person in session.query(Person).all():print(person)for team in session.query(teams).all():print(team)

output:

ID: 1  Name: Bob
ID: 2  Name: Anne
ID: 3  Name: Alice
ID: 4  Name: Joe
(1, 2)  # anne and joe are on bob's team
(1, 4)
(2, 3)  # alice is on anne's team
https://en.xdnf.cn/q/70522.html

Related Q&A

PyPy file append mode

I have code like this:f1 = open(file1, a) f2 = open(file1, a)f1.write(Test line 1\n) f2.write(Test line 2\n) f1.write(Test line 3\n) f2.write(Test line 4\n)When this code is run with standard Python 2.…

Clean up ugly WYSIWYG HTML code? Python or *nix utility

Im finally upgrading (rewriting ;) ) my first Django app, but I am migrating all the content. I foolishly gave users a full WYSIWYG editor for certain tasks, the HTML code produced is of course terribl…

Using config files written in Python [closed]

Closed. This question is opinion-based. It is not currently accepting answers.Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.Clo…

Model not defined when using foreign key to second model

Im trying to create several relationships between some models such as User and Country. When I try to syncdb, my console outputs "Name Country is not defined". Here is the code: class User(mo…

Sending a POST request to my RESTful API(Python-Flask), but receiving a GET request

Im trying to send a trigger to a Zapier webhook in the form of a POST request containing JSON. It works fine if I just send the POST request through a local python script.What I want to do is create a …

django deploy to Heroku : Server Error(500)

I am trying to deploy my app to heroku. Deploy was done correctly but I got Server Error(500). When I turned DEBUG true, Sever Error doesnt occurred. So I think there is something wrong with loading st…

Should I preallocate a numpy array?

I have a class and its method. The method repeats many times during execution. This method uses a numpy array as a temporary buffer. I dont need to store values inside the buffer between method calls. …

dup, dup2, tmpfile and stdout in python

This is a follow up question from here.Where I want do go I would like to be able to temporarily redirect the stdout into a temp file, while python still is able to print to stdout. This would involve …

How do I write a Class-Based Django Validator?

Im using Django 1.8.The documentation on writing validators has an example of a function-based validator. It also says the following on using a class:You can also use a class with a __call__() method f…

python synthesize midi with fluidsynth

I cant import fluidsynth. [Maybe theres an better module?]Im trying to synthesize midi from python or pygame. I can send midi events from pygame. Im using mingus, and it seemed pyfluidsynth would be g…