我有一个有亲子关系的班级:
Base = declarative_base()
class Parent(Base):
__tablename__ = "parent_table"
id = Column(Integer, primary_key=True)
children = relationship("Child", backref="parent")
def all_children(self):
pass # I want self.children + "Child where parent_id = NULL"
class Child(Base):
__tablename__ = "child_table"
id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey('parent_table.id')
我想向父母添加一个函数,该函数返回父亲在子关系中的子项,以及所有将其parent_id列设置为NULL的子对象。
整个情况有点复杂,因为类实际上是这样的联接表继承的情况:table_per_related,但我甚至不知道从哪里开始所以可能能够弄明白从那里。
(整个事情必须在通过Flask的Web服务环境中使用)
修改:更新。这是我真正想要做的最小实现,因为我无法将第一个答案翻译成在这种情况下有效的东西:
from sqlalchemy.ext.declarative import declarative_base, declared_attr
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy.orm import Session
from sqlalchemy import create_engine
class BaseCols:
id = Column(Integer, primary_key=True)
name = Column(String)
def __repr__(self):
return "<{}: {} - {}>".format(self.__class__.__name__, self.id, self.name)
@declared_attr
def __tablename__(cls):
return cls.__name__.lower()
Base = declarative_base(cls=BaseCols)
class Child(BaseCols):
pass
class HasChild:
@declared_attr
def children(cls):
cls.Child = type("{}Child".format(cls.__name__),
(Child, Base,),
dict(
__tablename__="{}_children".format(cls.__tablename__),
parent_id=Column(Integer, ForeignKey("{}.id".format(cls.__tablename__))),
parent=relationship(cls)
)
)
return relationship(cls.Child)
def all_children(self):
pass
class Foo(Base, HasChild):
__tablename__ = 'foo'
__mapper_args__ = {'concrete': True}
class Bar(Base, HasChild):
__tablename__ = 'bar'
__mapper_args__ = {'concrete': True}
if __name__ == "__main__":
engine = create_engine('sqlite://', echo=True)
Base.metadata.create_all(engine)
session = Session(engine)
session.add_all([
Foo(
name = "Foo the first!",
children = [
Foo.Child(name="Heir Apparent."),
Foo.Child(name="Spare.")
]
),
Foo(
name = "Foo the second...",
children = [
Foo.Child(name="Some child."),
]
),
Bar(
name = "Bar the first!",
children = [
Bar.Child(name="Bar's.")
]
),
Foo.Child(name="whoops"),
])
session.commit()
foo1 = session.query(Foo).first()
print(foo1)
print(foo1.children)
print(foo1.all_children(session))
答案 0 :(得分:2)
这样的东西?
class Child(Base):
# ...
class Parent(Base):
# ...
def all_children(self):
return Child.query.filter((Child.parent_id == self.id) | (Child.parent_id == None)).all()
请注意,我已将Child
课程移到Parent
之上,以便可以在all_children()
中引用它。
更新:以下是您添加到问题中的代码的实现:
def all_children(self, session):
cls = self.__class__.Child
return session.query(cls).filter((cls.parent_id == self.id) |
(cls.parent_id == None)).all()