РЕДАКТИРОВАТЬ: оригинальная версия почти работала.Следующая версия на самом деле работает.
Похоже, что вы пытаетесь сделать так, чтобы объект запроса был чем-то отличным от SELECT table.* FROM table
.В sqlalchemy вы можете сопоставить любой "выбираемый" с классом;Есть некоторые предостережения, хотя;если выбираемый не таблица, вставка данных может быть сложной.Нечто подобное приближается к работоспособному решению.Вы, вероятно, do хотите, чтобы обычная таблица отображалась для разрешения вставок, поэтому первая часть - это полностью обычная таблица, класс и сопоставитель.
blog_post_table = Table("blog_posts", metadata,
Column('id', Integer, primary_key=True),
Column('visible', Boolean, default=True),
...
)
class BlogPost(object):
pass
blog_post_mapper = mapper(BlogPost, blog_post_table)
Или, если вы использовалидекларативное расширение, все это будет один
class BlogPost(Base):
__tablename__ = 'blog_posts'
id = Column(Integer, primary_key=True)
visible = Column(Boolean, default=True)
Теперь нам нужно выражение select
для представления видимых сообщений.
visible_blog_posts_expr = sqlalchemy.sql.select(
[BlogPost.id,
BlogPost.visible]) \
.where(BlogPost.visible == True) \
.alias()
Или, так как присвоены имена всем столбцамжелаемого запроса утомительно (не говоря уже о нарушении DRY), вы можете использовать ту же конструкцию, что и session.query(BlogPost)
, и извлечь «оператор».Однако на самом деле вы не хотите, чтобы он был привязан к сеансу, поэтому вызывайте класс напрямую.
visible_blog_posts_expr = \
sqlalchemy.orm.Query(BlogPost) \
.filter(BlogPost.visible == True) \
.statement \
.alias()
И мы тоже это отображаем.
visible_blog_posts = mapper(BlogPost, visible_blog_posts_expr, non_primary=True)
Затем можно использовать visible_blog_posts
маппер вместо BlogPost
s с Session.query
, и вы все равно получите BlogPost
, который можно обновлять и сохранять как обычно.
posts = session.query(visible_blog_posts).all()
assert all(post.visible for post in posts)
Для этого конкретного примера естьнет большой разницы между явным mapper
использованием и декларативным расширением, вы все равно должны вызвать mapper
для неосновных отображений.В лучшем случае он позволяет вам набирать SomeClass.colname
вместо some_table.c.colname
(или SomeClass.__table__.colname
, или BlogPost.metadata.tables[BlogPost.__tablename__]
, или ... и т. Д.).
Ошибки, которые я допустил в исходном примере,которые сейчас исправлены.Я пропустил некоторые пропущенные []
в вызове sqlalchemy.sql.select, который ожидает, что столбцы будут в последовательности.при использовании оператора select
для mapper
sqlalchemy настаивает на том, чтобы оператор был псевдонимом, чтобы его можно было назвать (SELECT .... ) AS some_subselect_alias_5