在代理关联中使用JOIN

时间:2016-03-03 13:29:16

标签: python sqlalchemy

我在ContentContentRevision之间有代理关联。使用sqlalchemy.ext.associationproxy.association_proxy会产生EXISTS条件:

from sqlalchemy import create_engine, Column, Integer, Text, ForeignKey, inspect, String, and_
from sqlalchemy.ext.associationproxy import association_proxy
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship, foreign, remote

DeclarativeBase = declarative_base()


class ContentRevision(DeclarativeBase):
    __tablename__ = 'content_revision'

    revision_id = Column(Integer, primary_key=True)
    content_id = Column(Integer, ForeignKey('content.id'))
    description = Column(Text())
    title = Column(String(32))


class Content(DeclarativeBase):
    __tablename__ = 'content'

    id = Column(Integer, primary_key=True)
    revisions = relationship("ContentRevision",
                             foreign_keys=[ContentRevision.content_id])
    revision = relationship(
        "ContentRevision",
        uselist=False,
        primaryjoin=lambda: and_(
           remote(Content.id) == foreign(ContentRevision.content_id),
           ContentRevision.revision_id == ContentRevision.revision_id == session.query(ContentRevision.revision_id)
           .filter(ContentRevision.content_id == Content.id)
           .order_by(ContentRevision.revision_id.desc())
           .limit(1)
           .correlate(Content)
        ),
    )

    title = association_proxy('revision', 'title')
    description = association_proxy('revision', 'description')

# Prepare database and session

engine = create_engine('sqlite://', echo=False)
DeclarativeBase.metadata.create_all(engine)
session_maker = sessionmaker(engine)
session = session_maker()

#

c1 = Content()
c1.revisions.append(ContentRevision(title='rev', description='rev1'))

session.add(c1)
session.flush()

c1.revisions.append(ContentRevision(title='rev', description='rev2'))

assert [('rev', 'rev1'), ('rev', 'rev2')] == session.query(ContentRevision.title, ContentRevision.description).all()

print(str(session.query(Content).filter(Content.title == 'foo')))
"""
SELECT content.id AS content_id
FROM content
WHERE EXISTS (SELECT 1
FROM content_revision
WHERE content.id = content_revision.content_id AND content_revision.revision_id = (SELECT content_revision.revision_id AS content_revision_revision_id
FROM content_revision
WHERE content_revision.content_id = content.id ORDER BY content_revision.revision_id DESC
 LIMIT :param_1) AND content_revision.title = :title_1)
"""

如何使用Content.title primaryjoin 关系中声明的连接对关联列Content.revision进行查询?

0 个答案:

没有答案