From c8ca6edb22d7be24e13be66e482ce4b6ea342561 Mon Sep 17 00:00:00 2001 From: collerek Date: Wed, 2 Jun 2021 13:05:10 +0200 Subject: [PATCH] fix for not saving related model in reverse rel --- docs/relations/foreign-key.md | 6 ++- docs/releases.md | 3 ++ ormar/relations/relation_proxy.py | 2 +- tests/test_queries/db.sqlite | Bin 0 -> 12288 bytes tests/test_queries/test_adding_related.py | 54 ++++++++++++++++++++++ 5 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 tests/test_queries/db.sqlite create mode 100644 tests/test_queries/test_adding_related.py diff --git a/docs/relations/foreign-key.md b/docs/relations/foreign-key.md index 1bdc4f4..adc205c 100644 --- a/docs/relations/foreign-key.md +++ b/docs/relations/foreign-key.md @@ -99,7 +99,7 @@ course = Course(name="Math", completed=False) # note - not saved await department.courses.add(course) assert course.pk is not None # child model was saved # relation on child model is set and FK column saved in db -assert courses.department == department +assert course.department == department # relation on parent model is also set assert department.courses[0] == course ``` @@ -112,6 +112,10 @@ assert department.courses[0] == course That means that in example above the department has to be saved before you can call `department.courses.add()`. +!!!warning + This method will not work on `ManyToMany` relations - there, both sides of the relation have to be saved before adding to relation. + + ### remove Removal of the related model one by one. diff --git a/docs/releases.md b/docs/releases.md index 79d7622..9d72cbd 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -8,10 +8,13 @@ ## 🐛 Fixes * Fix is null filter with pagination and relations (by @erichaydel) [#214](https://github.com/collerek/ormar/issues/214) +* Fix not saving child object on reverse side of the relation if not saved before [#216](https://github.com/collerek/ormar/issues/216) + ## 💬 Other * Expand [fastapi](https://collerek.github.io/ormar/fastapi) part of the documentation to show samples of using ormar in requests and responses in fastapi. +* Improve the docs in regard of `default`, `ForeignKey.add` etc. # 0.10.9 diff --git a/ormar/relations/relation_proxy.py b/ormar/relations/relation_proxy.py index be3258c..baa6812 100644 --- a/ormar/relations/relation_proxy.py +++ b/ormar/relations/relation_proxy.py @@ -214,7 +214,7 @@ class RelationProxy(Generic[T], list): setattr(self._owner, self.field_name, item) else: setattr(item, relation_name, self._owner) - await item.update() + await item.upsert() await self._owner.signals.post_relation_add.send( sender=self._owner.__class__, instance=self._owner, diff --git a/tests/test_queries/db.sqlite b/tests/test_queries/db.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..80c5b0e4b688553f611cb8a2822b86e68bf15272 GIT binary patch literal 12288 zcmeI%!A{#S90qVZX<>~7;et5y@|UiZosTBBsB=)#e1 z&ym)Cw`;!|9gK(fcPdvY9fzSWoS=LpRrkpxAF5HlT(Ru^EWL9_UecMkBr8kpvd`@a z_l&G+6)zyG+o65?c{mKBSUSbF==!$5*lWL9e%jB{+AW=gQh299`3kF=Ws?*qLW;l@ z5mnvO`7R9mX@#$DZEy3ZXs%V8P>b3twc5bD<=%1_c6l~$nm?HN+nkxd%%4R>fdB*` z009U<00Izz00bZa0SG|g0}2>TowcJurbYv0G-_F|Wv!NZmFNHF&Ds3?{{cS@TY>-t mAOHafKmY;|fB*y_009U<;2#7Gt;se&@$)3VX&U?`>wf?%fupqm literal 0 HcmV?d00001 diff --git a/tests/test_queries/test_adding_related.py b/tests/test_queries/test_adding_related.py new file mode 100644 index 0000000..271a13c --- /dev/null +++ b/tests/test_queries/test_adding_related.py @@ -0,0 +1,54 @@ +from typing import Optional + +import databases +import pytest +import sqlalchemy +import asyncio + +import ormar + +from tests.settings import DATABASE_URL + +database = databases.Database(DATABASE_URL) +metadata = sqlalchemy.MetaData() + + +class Department(ormar.Model): + class Meta: + database = database + metadata = metadata + + id: int = ormar.Integer(primary_key=True) + name: str = ormar.String(max_length=100) + + +class Course(ormar.Model): + class Meta: + database = database + metadata = metadata + + id: int = ormar.Integer(primary_key=True) + name: str = ormar.String(max_length=100) + completed: bool = ormar.Boolean(default=False) + department: Optional[Department] = ormar.ForeignKey(Department) + + +@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_adding_relation_to_reverse_saves_the_child(): + async with database: + department = await Department(name="Science").save() + course = Course(name="Math", completed=False) + + await department.courses.add(course) + assert course.pk is not None + assert course.department == department + assert department.courses[0] == course