From f1c0ee336b8a35f6770135b9665f9beec3a4f1c5 Mon Sep 17 00:00:00 2001 From: collerek Date: Fri, 21 Oct 2022 14:38:16 +0200 Subject: [PATCH] Fix wrongly excluding relations if they were not in proper order and one of them were excluded. Fix for #779 (#890) --- ormar/models/model.py | 2 +- ormar/models/model_row.py | 2 +- .../test_excludes_in_load_all.py | 91 +++++++++++++++++++ 3 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 tests/test_model_methods/test_excludes_in_load_all.py diff --git a/ormar/models/model.py b/ormar/models/model.py index 509983c..7ff8e63 100644 --- a/ormar/models/model.py +++ b/ormar/models/model.py @@ -306,7 +306,7 @@ class Model(ModelRow): Allow to refresh existing Models fields from database. Performs refresh of the related models fields. - By default loads only self and the directly related ones. + By default, loads only self and the directly related ones. If follow=True is set it loads also related models of related models. diff --git a/ormar/models/model_row.py b/ormar/models/model_row.py index df90368..e3cf6ec 100644 --- a/ormar/models/model_row.py +++ b/ormar/models/model_row.py @@ -193,7 +193,7 @@ class ModelRow(NewBaseModel): model_cls=cast(Type["Model"], cls), alias=table_prefix ) if model_excludable.is_excluded(related): - return item + continue relation_str, remainder = cls._process_remainder_and_relation_string( related_models=related_models, diff --git a/tests/test_model_methods/test_excludes_in_load_all.py b/tests/test_model_methods/test_excludes_in_load_all.py new file mode 100644 index 0000000..66ee834 --- /dev/null +++ b/tests/test_model_methods/test_excludes_in_load_all.py @@ -0,0 +1,91 @@ +import asyncio +import uuid + +import pytest + +import ormar +import sqlalchemy +import databases + +from tests.settings import DATABASE_URL + +database = databases.Database(DATABASE_URL, force_rollback=True) +metadata = sqlalchemy.MetaData() + + +class BaseMeta: + metadata = metadata + database = database + + +class JimmyUser(ormar.Model): + class Meta(BaseMeta): + tablename = "jimmy_users" + + id: uuid.UUID = ormar.UUID( + primary_key=True, default=uuid.uuid4(), uuid_format="string" + ) + + +class JimmyProfile(ormar.Model): + class Meta(BaseMeta): + tablename = "jimmy_profiles" + + id: uuid.UUID = ormar.UUID( + primary_key=True, default=uuid.uuid4(), uuid_format="string" + ) + name = ormar.String(max_length=42, default="JimmyProfile") + + user: JimmyUser = ormar.ForeignKey(to=JimmyUser) + + +class JimmyAccount(ormar.Model): + class Meta(BaseMeta): + tablename = "jimmy_accounts" + + id: uuid.UUID = ormar.UUID( + primary_key=True, default=uuid.uuid4(), uuid_format="string" + ) + + name = ormar.String(max_length=42, default="JimmyAccount") + + user: JimmyUser = ormar.ForeignKey(to=JimmyUser) + + +@pytest.fixture(autouse=True, scope="module") +def create_test_database(): + engine = sqlalchemy.create_engine(DATABASE_URL) + metadata.drop_all(engine) + metadata.create_all(engine) + yield + metadata.drop_all(engine) + + +@pytest.mark.asyncio +async def test_excluding_one_relation(): + async with database: + user = JimmyUser() + await user.save() + + await JimmyAccount(user=user).save() + await JimmyProfile(user=user).save() + + await user.load_all(exclude={"jimmyprofiles"}) + assert hasattr(user.jimmyaccounts[0], "name") + assert len(user.jimmyprofiles) == 0 + + +@pytest.mark.asyncio +async def test_excluding_other_relation(): + async with database: + user = JimmyUser() + await user.save() + + await JimmyAccount(user=user).save() + await JimmyProfile(user=user).save() + + await user.load_all(exclude={"jimmyaccounts"}) + assert await JimmyProfile.objects.get() + + assert hasattr(user.jimmyprofiles[0], "name") + assert len(user.jimmyaccounts) == 0