From 7666119f3118e67ca2d23123c80e1d4d908145a4 Mon Sep 17 00:00:00 2001 From: Miroslav Shubernetskiy Date: Wed, 8 Aug 2018 14:01:08 -0400 Subject: [PATCH] not joining already eager loaded models --- HISTORY.rst | 6 ++++++ tests/backends/test_sqlalchemy.py | 15 +++++++++++++++ url_filter/__init__.py | 2 +- url_filter/backends/sqlalchemy.py | 4 ++++ 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/HISTORY.rst b/HISTORY.rst index 828b772..189a249 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -3,6 +3,12 @@ History ------- +0.3.8 (2018-08-08) +~~~~~~~~~~~~~~~~~~ + +* Fixed ``SQLAlchemyFilterBackend`` by not joining nested models + when they are already eager loaded via ``query.options()``. + 0.3.7 (2018-07-27) ~~~~~~~~~~~~~~~~~~ diff --git a/tests/backends/test_sqlalchemy.py b/tests/backends/test_sqlalchemy.py index 335590d..c2840cc 100644 --- a/tests/backends/test_sqlalchemy.py +++ b/tests/backends/test_sqlalchemy.py @@ -5,6 +5,7 @@ import six from alchemy_mock.comparison import ExpressionMatcher from sqlalchemy import func +from sqlalchemy.orm import joinedload from sqlalchemy.types import String from test_project.one_to_one.alchemy import Place, Restaurant, Waiter @@ -75,6 +76,20 @@ def test_filter(self, alchemy_db): '\nWHERE one_to_one_waiter.name ={}'.format(sql.rsplit('=', 1)[-1]) ) + def test_filter_already_eagerloaded(self, alchemy_db): + backend = SQLAlchemyFilterBackend( + alchemy_db.query(Place).options(joinedload(Place.restaurant).joinedload(Restaurant.waiter_set)), + ) + backend.bind([ + FilterSpec(['restaurant', 'waiter_set', 'name'], 'exact', 'John', False), + ]) + + filtered = backend.filter() + + sql = six.text_type(filtered) + assert 'place JOIN one_to_one' not in sql + assert 'place LEFT OUTER JOIN one_to_one' in sql + def _test_build_clause(self, alchemy_db, name, lookup, value, expected, is_negated=False): backend = SQLAlchemyFilterBackend( alchemy_db.query(Place), diff --git a/url_filter/__init__.py b/url_filter/__init__.py index 0cad69c..de10cd1 100644 --- a/url_filter/__init__.py +++ b/url_filter/__init__.py @@ -4,4 +4,4 @@ __author__ = 'Miroslav Shubernetskiy' __email__ = 'miroslav@miki725.com' -__version__ = '0.3.7' +__version__ = '0.3.8' diff --git a/url_filter/backends/sqlalchemy.py b/url_filter/backends/sqlalchemy.py index 09f328c..27dc96a 100644 --- a/url_filter/backends/sqlalchemy.py +++ b/url_filter/backends/sqlalchemy.py @@ -127,6 +127,10 @@ def build_clause(self, spec): else: to_join.append(_field) + existing_eagerloads = [list(i.path) for i in self.queryset._with_options] + if to_join in existing_eagerloads: + to_join = [] + builder = getattr(self, '_build_clause_{}'.format(spec.lookup)) column = self._get_attribute_for_field(field) clause = builder(spec, column)