I’m using SQLAlchemy and I what I liked with Django ORM was the Manager I could implement to override the initial query of an object.
Is something like this exist in SQLAlchemy? I’d like to always exclude items that have “visible = False”, when I do something like :
session.query(BlogPost).all()
Is it possible?
Thanks!
EDIT: the original version almost worked. The following version actually works.
It sounds like what you’re trying to do is arrange for the query entity to be something other than
SELECT table.* FROM table. In sqlalchemy, you can map any “selectable” to a class; There are some caveats, though; if the selectable is not a table, inserting data can be tricky. Something like this approaches a workable solution. You probably do want to have a regular table mapped to permit inserts, so the first part is a totally normal table, class and mapper.Or, if you were using the declarative extension, it’ll all be one
Now, we need a
selectexpression to represent the visible posts.Or, since naming all of the columns of the desired query is tedious (not to mention in violation of DRY), you can use the same construct as
session.query(BlogPost)and extract the ‘statement’. You don’t actually want it bound to a session, though, so call the class directly.And we map that too.
You can then use the
visible_blog_postsmapper instead ofBlogPosts withSession.query, and you will still getBlogPost, which can be updated and saved as normal.For this particular example, there’s not much difference between explicit
mapperuse and declarative extension, you still must callmapperfor the non-primary mappings. At best, it allows you to typeSomeClass.colnameinstead ofsome_table.c.colname(orSomeClass.__table__.colname, orBlogPost.metadata.tables[BlogPost.__tablename__]or … and so on).The mistakes I made in the original example, which are now corrected. I was missing some missing
[]‘s in the call to sqlalchemy.sql.select, which expects the columns to be in a sequence. when using aselectstatement tomapper, sqlalchemy insists that the statement be aliased, so that it can be named(SELECT .... ) AS some_subselect_alias_5