Constructing hierarchy from dictionary/JSON

邮差的信 提交于 2019-12-13 12:04:48

问题


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, String

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'))

    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.


回答1:


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.id
            self.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: 1
    Name: Bob
    ParentID: None


    ID: 2
    Name: Anne
    ParentID: 1


    ID: 3
    Name: Joe
    ParentID: 1


    ID: 4
    Name: Alice
    ParentID: 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://stackoverflow.com/questions/49800747/constructing-hierarchy-from-dictionary-json

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!