У меня есть класс, который имеет отношения родитель-потомок:SQLAlchemy: найти дочерние объекты в отношениях с NULL родителя
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, но я даже не знаю, с чего начать, поэтому, вероятно, сможет понять это оттуда.
(Все это должно быть полезной в контексте веб-сервиса через колба)
Edit: Update. Это минимальная реализация того, что я действительно хотел сделать, так как я не могу вполне удается перевести первый ответ в то, что работает в этом контексте:
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))
Да! У меня все еще есть несколько деталей, которые можно найти с помощью table_per_related setup, но отправьте сообщение, если я столкнусь с другими трудностями. Поскольку я не сталкивался с этим в своих поисках, где документирован синтаксис Class.query? – kai
Синтаксис 'class.query' от Flask-SQLAlchemy. Если вы используете простой SQLAlchemy, эквивалентным синтаксисом является 'session.query (Class)'. См. Http://docs.sqlalchemy.org/en/rel_0_9/orm/query.html – Miguel
Ах, правильно. Глядя в совершенно неправильное место тогда. – kai