add save_all, some optimizations

This commit is contained in:
collerek
2021-03-26 16:28:34 +01:00
parent 8f60593123
commit 5a3b170d06
3 changed files with 30 additions and 5 deletions

View File

@ -1,9 +1,19 @@
# 0.10.2 # 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 ## Fixes
* Fix improper relation field resolution in `QuerysetProxy` if fk column has different database alias. * Fix improper relation field resolution in `QuerysetProxy` if fk column has different database alias.
## Other
* Performance optimizations
# 0.10.1 # 0.10.1

View File

@ -101,7 +101,11 @@ class Model(ModelRow):
return self return self
async def save_related( # noqa: CCR001 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 ) -> int: # noqa: CCR001
""" """
Triggers a upsert method on all related models Triggers a upsert method on all related models
@ -145,6 +149,7 @@ class Model(ModelRow):
update_count, visited = await self._update_and_follow( update_count, visited = await self._update_and_follow(
rel=rel, rel=rel,
follow=follow, follow=follow,
save_all=save_all,
visited=visited, visited=visited,
update_count=update_count, update_count=update_count,
) )
@ -152,14 +157,18 @@ class Model(ModelRow):
else: else:
rel = getattr(self, related) rel = getattr(self, related)
update_count, visited = await self._update_and_follow( 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__) visited.add(rel.__class__)
return update_count return update_count
@staticmethod @staticmethod
async def _update_and_follow( 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]: ) -> Tuple[int, Set]:
""" """
Internal method used in save_related to follow related models and update numbers 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: if follow and rel.__class__ not in visited:
update_count = await rel.save_related( 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() await rel.upsert()
update_count += 1 update_count += 1
return update_count, visited return update_count, visited

View File

@ -110,6 +110,9 @@ async def test_saving_many_to_many():
count = await hq.save_related() count = await hq.save_related()
assert count == 0 assert count == 0
count = await hq.save_related(save_all=True)
assert count == 2
hq.nicks[0].name = "Kabucha" hq.nicks[0].name = "Kabucha"
hq.nicks[1].name = "Kabucha2" hq.nicks[1].name = "Kabucha2"
assert not hq.nicks[0].saved assert not hq.nicks[0].saved