Ahmed
Ahmed

Reputation: 103

The underlying query of a mapped attribute

If I have an sqlalchemy-mapped instance. Can I get an underlying dynamic query object corresponding to an attribute of said instance?

For example:

e = Employee()
e.projects

#how do I get a query object loaded with the underlying sql of e.projects

Upvotes: 1

Views: 119

Answers (2)

SingleNegationElimination
SingleNegationElimination

Reputation: 156278

I think you're describing the lazy="dynamic" property of relationship(). something like

 class Employee(Base):
     __table_name__ = "employees"
     ...

     projects = relationship(..., lazy="dynamic")

which will cause Employee().project to return a sqlalchemy.orm.Query instance instead of a collection containing the related items. However, that means there's no (simple) way to access the collection directly. If you still need that (most likely you really do want it to be lazily loaded, set up two relationship()s instead.

 class Employee(Base):
     __table_name__ = "employees"
     ...

     projects_query = relationship(..., lazy="dynamic")
     projects = relationship(..., lazy="select")

edit: You said

I need somehow to get the dynamic query object of an already lazy relationship mapped property.

Supposing we have an instance i of class Foo related to a class Bar by the property bars. First, we need to get the property that handles the relationship.

from sqlalchemy.orm.attributes import manager_of_class
p = manager_of_class(Foo).mapper.get_property('bars')

We'd like an expression that and_s together all of the columns on i that relate it to bars. If you need to operate on Foo through an alias, substitute it in here.

e = sqlalchemy.and_(*[getattr(Foo, c.key) == getattr(i, c.key)
                      for c in p.local_side])

Now we can create a query that expresses this relationship. Substitute aliases for Foo and Bar here as needed.

q = session.query(Foo) \
           .filter(e) \
           .join(Foo.bars) \
           .with_entities(Bar)

Upvotes: 2

van
van

Reputation: 77082

Not sure about the question in general, but you definitely can enable SQL logging by setting echo=True, which will log the SQL statement as soon as you try to get value of the attribute.
Depending on your relationship configuration, it might have been eagerly pre-loaded.

Upvotes: 0

Related Questions