With SQLAlchemy, is there a way to know beforehand whether a relation would be lazy-loaded?
For example, given a lazy parent->children relation and an instance X of "parent", I'd like to know if "X.children" is already loaded, without triggering the query.
Lazy loading refers to objects are returned from a query without the related objects loaded at first. When the given collection or reference is first accessed on a particular object, an additional SELECT statement is emitted such that the requested collection is loaded.
At the ORM level, the speed issues are because creating objects in Python is slow, and the SQLAlchemy ORM applies a large amount of bookkeeping to these objects as it fetches them, which is necessary in order for it to fulfill its usage contract, including unit of work, identity map, eager loading, collections, etc.
first() applies a limit of one within the generated SQL, so that only one primary entity row is generated on the server side (note this may consist of multiple result rows if join-loaded collections are present). Calling Query. first() results in an execution of the underlying query.
The alias in SQL corresponds to a “renamed” version of a table or SELECT statement, which occurs anytime you say “SELECT * FROM table1 AS a”. The AS creates a new name for the table. Aliases allow any table or subquery to be referenced by a unique name.
You can get a list of all unloaded properties (both relations and columns) from sqlalchemy.orm.attributes.instance_state(obj).unloaded
.
See: Completing object with its relations and avoiding unnecessary queries in sqlalchemy
An easier way is to use inspect()
, which gives the same results:
from sqlalchemy import inspect
from sqlalchemy.orm import lazyload
user = session.query(User).options(lazyload(User.articles)).first()
ins = inspect(user)
ins.unloaded # <- set or properties that are not yet loaded
I think you could look at the child's __dict__
attribute dictionary to check if the data is already there or not.
Slightly neater than Haes answer (though it effectively does the same thing) is to use hasattr(), as in:
>>> hasattr(X, 'children')
False
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With