SQLAlchemy - отношения ограничены не только внешним ключом - PullRequest
4 голосов
/ 29 мая 2010

У меня есть макет вики-базы данных с Page и Revisions. Каждая ревизия имеет page_id ссылку на страницу, page отношение к ссылочной странице; каждая страница имеет отношение all_revisions ко всем ее ревизиям. Пока что так часто.

Но я хочу реализовать разные эпохи для страниц: если страница была удалена и воссоздана, новые ревизии имеют новую epoch. Чтобы помочь найти правильные ревизии, каждая страница имеет поле current_epoch. Теперь я хочу предоставить revisions отношение на странице, которое содержит только его ревизии, но только те, где совпадают эпохи.

Вот что я пробовал:

revisions = relationship('Revision',
    primaryjoin = and_(
        'Page.id == Revision.page_id',
        'Page.current_epoch == Revision.epoch',
    ),
    foreign_keys=['Page.id', 'Page.current_epoch']
)

Полный код (вы можете запустить его как есть)

Однако это всегда вызывает ArgumentError: Не удалось определить направление отношений для условия первичного соединения ... `, я перепробовал все, что мне пришло в голову, это не сработало.

Что я делаю не так? Это плохой подход для этого, как это может быть сделано, кроме как с отношениями?

1 Ответ

4 голосов
/ 31 мая 2010

Попробуйте установить отношения после создания обоих классов:

Page.revisions = relationship(
    'Revision',
    primaryjoin = (Page.id==Revision.page_id) & \
                    (Page.current_epoch==Revision.epoch),
    foreign_keys=[Page.id, Page.current_epoch],
    uselist=True,
)

Кстати, ваш тест неверен: revisions свойство загружает данные из базы данных, пока вы не добавили их в сеанс.

Обновление : проблема в вашем коде в том, что параметр primaryjoin не является строкой, поэтому не оценивается . Использование строки в primaryjoin отлично работает:

class Page(Base):
    # [skipped]
    revisions = relationship(
        'Revision',
        primaryjoin = '(Page.id==Revision.page_id) & '\
                        '(Page.current_epoch==Revision.epoch)',
        foreign_keys=[id, current_epoch],
        uselist=True,
    )
...