From 5a3b170d06e9553d816368a853c4b870e4766b14 Mon Sep 17 00:00:00 2001 From: collerek Date: Fri, 26 Mar 2021 16:28:34 +0100 Subject: [PATCH] add save_all, some optimizations --- docs/releases.md | 10 ++++++++++ ormar/models/model.py | 22 +++++++++++++++++----- tests/test_save_related.py | 3 +++ 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/docs/releases.md b/docs/releases.md index 6d18c0f..210bb93 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -1,9 +1,19 @@ # 0.10.2 +## Features + +* `save_related(follow=False)` now accept also second argument `save_related(follow=False, save_all=False)`. + By default so with `save_all=False` `ormar` only upserts models that are no saved (so new or updated ones), + with `save_all=True` all related models are saved, regardless of `saved` status, which might be usefull if updated + models comes from api call, so are not changed in backend. + ## Fixes * Fix improper relation field resolution in `QuerysetProxy` if fk column has different database alias. +## Other + +* Performance optimizations # 0.10.1 diff --git a/ormar/models/model.py b/ormar/models/model.py index 6a46696..cf4b653 100644 --- a/ormar/models/model.py +++ b/ormar/models/model.py @@ -101,7 +101,11 @@ class Model(ModelRow): return self async def save_related( # noqa: CCR001 - self, follow: bool = False, visited: Set = None, update_count: int = 0 + self, + follow: bool = False, + save_all: bool = False, + visited: Set = None, + update_count: int = 0, ) -> int: # noqa: CCR001 """ Triggers a upsert method on all related models @@ -145,6 +149,7 @@ class Model(ModelRow): update_count, visited = await self._update_and_follow( rel=rel, follow=follow, + save_all=save_all, visited=visited, update_count=update_count, ) @@ -152,14 +157,18 @@ class Model(ModelRow): else: rel = getattr(self, related) update_count, visited = await self._update_and_follow( - rel=rel, follow=follow, visited=visited, update_count=update_count + rel=rel, + follow=follow, + save_all=save_all, + visited=visited, + update_count=update_count, ) visited.add(rel.__class__) return update_count @staticmethod async def _update_and_follow( - rel: "Model", follow: bool, visited: Set, update_count: int + rel: "Model", follow: bool, save_all: bool, visited: Set, update_count: int ) -> Tuple[int, Set]: """ Internal method used in save_related to follow related models and update numbers @@ -181,9 +190,12 @@ class Model(ModelRow): """ if follow and rel.__class__ not in visited: update_count = await rel.save_related( - follow=follow, visited=visited, update_count=update_count + follow=follow, + save_all=save_all, + visited=visited, + update_count=update_count, ) - if not rel.saved: + if not rel.saved or save_all: await rel.upsert() update_count += 1 return update_count, visited diff --git a/tests/test_save_related.py b/tests/test_save_related.py index fc9f3ff..8609353 100644 --- a/tests/test_save_related.py +++ b/tests/test_save_related.py @@ -110,6 +110,9 @@ async def test_saving_many_to_many(): count = await hq.save_related() assert count == 0 + count = await hq.save_related(save_all=True) + assert count == 2 + hq.nicks[0].name = "Kabucha" hq.nicks[1].name = "Kabucha2" assert not hq.nicks[0].saved