我在Content
和ContentRevision
之间有代理关联。使用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
进行查询?