从 dictionary/JSON 构建层次结构

Constructing hierarchy from dictionary/JSON

我正在寻找一种在两个或多个相同 class 实例之间以子父关系形式创建层次结构的方法。

如何像示例中那样从嵌套字典创建此类对象?这可能吗?有没有其他推荐的方法来完成这样的任务?

# -*- 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()

我理解迭代方法,我首先创建父对象,然后遍历可能的子对象并创建它们。我很好奇是否有一种方法可以在构造函数内部执行此操作,而不是从 'outside' 循环执行此操作。

试试这个。

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

输出:

    ID: 1
    Name: Bob
    ParentID: None
            

    ID: 2
    Name: Anne
    ParentID: 1
            

    ID: 3
    Name: Joe
    ParentID: 1
            

    ID: 4
    Name: Alice
    ParentID: 2

当我 运行 在已保存的数据库上执行此操作时,(engine = create_engine('sqlite:///delme.db'),并且 运行 它多次执行,它会在一次添加和提交时创建所有条目。

不同的方法

您也可以创建一个单独的“团队”table 来存储团队负责人和团队成员

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

输出:

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