summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm
diff options
context:
space:
mode:
authorsanjana <sanjana0796@gmail.com>2019-02-19 23:07:12 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2019-02-20 17:08:34 -0500
commitc89a93e9530511d54fa73c76c32cee11eaa418df (patch)
tree8bde4bca9595bf4c79af3a02a793192ccc42590d /lib/sqlalchemy/orm
parentd71f34cb2a28e8dfc410bc5bec68372be6d7c333 (diff)
downloadsqlalchemy-c89a93e9530511d54fa73c76c32cee11eaa418df.tar.gz
Add support for key-word based get()
The :meth:`.Query.get` method can now accept a dictionary of attribute keys and values as a means of indicating the primary key value to load; is particularly useful for composite primary keys. Pull request courtesy Sanjana S. Fixes: #4316 Closes: #4505 Pull-request: https://github.com/sqlalchemy/sqlalchemy/pull/4505 Pull-request-sha: cfa8297ad2490be9eae24ec8b1a691e43cd75868 Change-Id: Ib19e7d51599a36f4878119c2f801c5c694793422
Diffstat (limited to 'lib/sqlalchemy/orm')
-rw-r--r--lib/sqlalchemy/orm/query.py65
1 files changed, 55 insertions, 10 deletions
diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py
index f86cb9085..db8d8bcbe 100644
--- a/lib/sqlalchemy/orm/query.py
+++ b/lib/sqlalchemy/orm/query.py
@@ -883,6 +883,9 @@ class Query(object):
some_object = session.query(VersionedFoo).get((5, 10))
+ some_object = session.query(VersionedFoo).get(
+ {"id": 5, "version_id": 10})
+
:meth:`~.Query.get` is special in that it provides direct
access to the identity map of the owning :class:`.Session`.
If the given primary key identifier is present
@@ -918,14 +921,37 @@ class Query(object):
before querying the database. See :doc:`/orm/loading_relationships`
for further details on relationship loading.
- :param ident: A scalar or tuple value representing
- the primary key. For a composite primary key,
- the order of identifiers corresponds in most cases
- to that of the mapped :class:`.Table` object's
- primary key columns. For a :func:`.mapper` that
- was given the ``primary key`` argument during
- construction, the order of identifiers corresponds
- to the elements present in this collection.
+ :param ident: A scalar, tuple, or dictionary representing the
+ primary key. For a composite (e.g. multiple column) primary key,
+ a tuple or dictionary should be passed.
+
+ For a single-column primary key, the scalar calling form is typically
+ the most expedient. If the primary key of a row is the value "5",
+ the call looks like::
+
+ my_object = query.get(5)
+
+ The tuple form contains primary key values typically in
+ the order in which they correspond to the mapped :class:`.Table`
+ object's primary key columns, or if the
+ :paramref:`.Mapper.primary_key` configuration parameter were used, in
+ the order used for that parameter. For example, if the primary key
+ of a row is represented by the integer
+ digits "5, 10" the call would look like::
+
+ my_object = query.get((5, 10))
+
+ The dictionary form should include as keys the mapped attribute names
+ corresponding to each element of the primary key. If the mapped class
+ has the attributes ``id``, ``version_id`` as the attributes which
+ store the object's primary key value, the call would look like::
+
+ my_object = query.get({"id": 5, "version_id": 10})
+
+ .. versionadded:: 1.3 the :meth:`.Query.get` method now optionally
+ accepts a dictionary of attribute names to values in order to
+ indicate a primary key identifier.
+
:return: The object instance, or ``None``.
@@ -991,10 +1017,12 @@ class Query(object):
if hasattr(primary_key_identity, "__composite_values__"):
primary_key_identity = primary_key_identity.__composite_values__()
- primary_key_identity = util.to_list(primary_key_identity)
-
mapper = self._only_full_mapper_zero("get")
+ is_dict = isinstance(primary_key_identity, dict)
+ if not is_dict:
+ primary_key_identity = util.to_list(primary_key_identity)
+
if len(primary_key_identity) != len(mapper.primary_key):
raise sa_exc.InvalidRequestError(
"Incorrect number of values in identifier to formulate "
@@ -1002,6 +1030,23 @@ class Query(object):
% ",".join("'%s'" % c for c in mapper.primary_key)
)
+ if is_dict:
+ try:
+ primary_key_identity = list(
+ primary_key_identity[prop.key]
+ for prop in mapper._identity_key_props
+ )
+
+ except KeyError:
+ raise sa_exc.InvalidRequestError(
+ "Incorrect names of values in identifier to formulate "
+ "primary key for query.get(); primary key attribute names"
+ " are %s" % ",".join(
+ "'%s'" % prop.key
+ for prop in mapper._identity_key_props
+ )
+ )
+
if (
not self._populate_existing
and not mapper.always_refresh