Skip to content

Commit

Permalink
Use Session.get() in get_instance instead of Session.query() (#548)
Browse files Browse the repository at this point in the history
* Use Session.get() in `get_instance` instead of Session.query()

Session.get() tries to fetch an object from the session's identity map if it exists, and performs a SQL query otherwise.

This can help improve load performance by reducing number of SQL queries, especially for nested relationships, if everything is already available into the session.

* Update changelog

---------

Co-authored-by: Steven Loria <sloria1@gmail.com>
  • Loading branch information
zippolyte and sloria committed Jan 7, 2024
1 parent 572093e commit 7570f00
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 2 deletions.
3 changes: 2 additions & 1 deletion AUTHORS.rst
Expand Up @@ -43,4 +43,5 @@ Contributors
- Justin Crown `@mrname <https://github.com/mrname>`_
- Jeppe Fihl-Pearson `@Tenzer <https://github.com/Tenzer>`_
- Indivar `@indiVar0508 <https://github.com/indiVar0508>`_
- David Doyon `@ddoyon92 <https://github.com/ddoyon92>`_
- David Doyon `@ddoyon92 <https://github.com/ddoyon92>`_
- Hippolyte Henry `@zippolyte <https://github.com/zippolyte>`_
5 changes: 5 additions & 0 deletions CHANGELOG.rst
Expand Up @@ -4,6 +4,11 @@ Changelog
0.30.0 (unreleased)
+++++++++++++++++++

Features:

* Use ``Session.get()`` load instances to improve deserialization performance (:pr:`548`).
Thanks :user:`zippolyte` for the PR.

Other changes:

* Drop support for Python 3.7, which is EOL (:pr:`540`).
Expand Down
6 changes: 5 additions & 1 deletion src/marshmallow_sqlalchemy/load_instance_mixin.py
Expand Up @@ -6,6 +6,7 @@
Users should not need to use this module directly.
"""
import marshmallow as ma
from sqlalchemy.orm.exc import ObjectDeletedError

from .fields import get_primary_keys

Expand Down Expand Up @@ -55,7 +56,10 @@ def get_instance(self, data):
props = get_primary_keys(self.opts.model)
filters = {prop.key: data.get(prop.key) for prop in props}
if None not in filters.values():
return self.session.query(self.opts.model).filter_by(**filters).first()
try:
return self.session.get(self.opts.model, filters)
except ObjectDeletedError:
return None
return None

@ma.post_load
Expand Down

0 comments on commit 7570f00

Please sign in to comment.