Как я могу указать SQLAlchemy на загрузку отношений «один ко многим»? Я мог бы присоединиться к ним, но это вызывает дубликаты и (в зависимости от размера результата) много накладных расходов. В идеале я хотел бы изменить session.query
таким образом, чтобы было отправлено несколько (двух) запросов, возвращающих родителей и все их дочерние объекты. Как это возможно, либо путем настройки SQLA, либо расширения класса сеанса? Или, может быть, это не обычный способ делать что-то в SQLA ...SQLAlchemy извлекает объекты «один ко многим» подзапросом
ответ
Отношение «один ко многим» обычно выполняется путем создания атрибута списка в классе «Родительский» («один») и «родительский» backreference в Child (,, many '') класс (смотрите здесь: here).
Таким образом, вы вообще создать родительский класс:
class Parent(Base):
__tablename__ = "parents"
dbid = Column(Integer, Sequence("parent_seq"), primary_key=True)
children = relationship("Child", order_by = "Children.dbid", backref = "_parent")
def __init__(self, children = [])
self.children = children #remember to initialize children as list!
И Детский класс:
class Child(Base):
__tablename__ = "children"
dbid = Column(Integer, Sequence("child_seq"), primary_key=True)
parent_dbid = Column(Integer, ForeignKey("parents.dbid"))
Если вы хотите добавить ребенка к родителю, просто сделать это так:
p = Parent()
c = Child()
p.children.append(c)
session.add(p)
session.add(c)
session.commit()
Затем, если вы хотите загрузить родителя со всеми его дочерними элементами, вы просто загрузите родителя с session.query(...)
и дети загружаются автоматически - вам не нужно делать какие-либо соединения, если вы не хотите, например, загружать только родителей, чьи дети имеют определенные значения атрибутов.
Надеюсь, что это поможет. Пожалуйста, напишите комментарий, если что-то неясно - я попытаюсь изменить свой ответ, чтобы указать.
Спасибо за ваш ответ. Сколько запросов будет отправлено SQLA для извлечения всех детей из нескольких родителей? – orange
Это зависит от структуры вашей базы данных и, возможно, от того, какой механизм БД вы используете. Самый простой способ проверить - включить печать всех запросов, которые делает SQLA. Вы можете сделать это при создании движка: 'engine = create_engine (" path_to_your_database ", echo = True)'. Затем создайте сеанс следующим образом: 'Session = sessionmaker (bind = engine)' и 'session = Session()'. Постскриптум Если вам нравится мой ответ, пожалуйста, примите это;). – Wookie88
SQLA, похоже, по умолчанию запрашивает дочерние элементы для каждого родителя. Поведение можно изменить, добавив параметр «lazy» в поле отношений (см. Http://docs.sqlalchemy.org/en/rel_0_7/orm/loading.html#using-loader-strategies-lazy-loading-eager- загрузка). – orange