Построить все дерево из отношения списка смежности SQLAlchemy - PullRequest
9 голосов
/ 15 апреля 2011

У меня есть класс Node с самореференциальным отображением 'children' (backref 'parent'), представляющим дерево в SQLAlchemy, и я хочу выбрать все дерево. Если я сделаю

session.query(Node).all()

тогда каждый доступ к node.children вызывает выбор. Если я делаю совместную нагрузку

session.query(Node).options(joinedload_all('children')).all()

тогда в выданном sql есть ненужное объединение таблиц, так как я в любом случае хочу все дерево (все узлы). Есть ли способ сделать это в SA или я должен просто построить дерево самостоятельно вне SA?

1 Ответ

12 голосов
/ 18 апреля 2011

Нет проблем с родительским свойством, так как вся необходимая информация уже загружена в объект.SQLAlchemy просто нужно искать родительский объект в сеансе и выдавать запрос только тогда, когда он отсутствует.Но это не работает для детей: библиотека не может быть уверена, что все дочерние объекты уже находятся в сеансе.Таким образом, вы можете построить дерево самостоятельно и указать SQLAlchemy использовать эти данные через set_committed_value:

from collections import defaultdict
from sqlalchemy.orm.attributes import set_committed_value

nodes = session.query(Node).all()

# Collect parent-child relations
children = defaultdict(list)
for node in nodes:
    if node.parent:
        children[node.parent.id].append(node)

# Set collected values
for node in nodes:
    set_committed_value(node, 'children', children[node.id])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...