* On an object where :func:`.query_expression` were not used to populate
the attribute, the attribute on an object instance will have the value
- ``None``.
+ ``None``, unless the :paramref:`_orm.query_expression.default_expr`
+ parameter is set to an alternate SQL expression.
+
+* The query_expression value **does not populate on an object that is
+ already loaded**. That is, this will **not work**::
+
+ obj = session.query(A).first()
+
+ obj = session.query(A).options(with_expression(A.expr, some_expr)).first()
+
+ To ensure the attribute is re-loaded, use :meth:`_orm.Query.populate_existing`::
+
+ obj = session.query(A).populate_existing().options(
+ with_expression(A.expr, some_expr)).first()
* The query_expression value **does not refresh when the object is
expired**. Once the object is expired, either via :meth:`.Session.expire`
:param expr: SQL expression to be applied to the attribute.
+ .. note:: the target attribute is populated only if the target object
+ is **not currently loaded** in the current :class:`_orm.Session`
+ unless the :meth:`_orm.Query.populate_existing` method is used.
+ Please refer to :ref:`mapper_querytime_expression` for complete
+ usage details.
+
.. seealso::
:ref:`mapper_querytime_expression`
q.all(), [A(bs=[B(b_expr=25)]), A(bs=[B(b_expr=38), B(b_expr=10)])]
)
+ def test_no_refresh_unless_populate_existing(self):
+ A = self.classes.A
+
+ s = Session()
+ a1 = s.query(A).first()
+
+ def go():
+ eq_(a1.my_expr, None)
+
+ self.assert_sql_count(testing.db, go, 0)
+
+ a1 = s.query(A).options(with_expression(A.my_expr, A.x + A.y)).first()
+
+ eq_(a1.my_expr, None)
+
+ a1 = (
+ s.query(A)
+ .populate_existing()
+ .options(with_expression(A.my_expr, A.x + A.y))
+ .first()
+ )
+
+ eq_(a1.my_expr, 3)
+
+ a1 = s.query(A).first()
+
+ eq_(a1.my_expr, 3)
+
+ s.expire(a1)
+
+ eq_(a1.my_expr, None)
+
def test_no_sql_not_set_up(self):
A = self.classes.A