From 0aaedeeca74fd7d6b011b4c30b283c08f5208cb2 Mon Sep 17 00:00:00 2001 From: tarsil Date: Wed, 24 Jan 2024 20:53:48 +0000 Subject: [PATCH] Fix update on save() for fields --- docs/fields.md | 12 +++--- saffier/core/db/models/model.py | 13 +------ tests/models/test_datetime.py | 66 +++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 17 deletions(-) create mode 100644 tests/models/test_datetime.py diff --git a/docs/fields.md b/docs/fields.md index f6569e6..07cc098 100644 --- a/docs/fields.md +++ b/docs/fields.md @@ -180,9 +180,9 @@ class MyModel(saffier.Model): ##### Parameters -* **auto_now** - A boolean indicating the `auto_now` enabled. -* **auto_now_add** - A boolean indicating the `auto_now_add` enabled. - +* **auto_now** - A boolean indicating the `auto_now` enabled. Useful for auto updates. +* **auto_now_add** - A boolean indicating the `auto_now_add` enabled. This will ensure that its +only added once. #### DateTimeField @@ -199,9 +199,9 @@ class MyModel(saffier.Model): ##### Parameters -* **auto_now** - A boolean indicating the `auto_now` enabled. -* **auto_now_add** - A boolean indicating the `auto_now_add` enabled. - +* **auto_now** - A boolean indicating the `auto_now` enabled. Useful for auto updates. +* **auto_now_add** - A boolean indicating the `auto_now_add` enabled. This will ensure that its +only added once. #### DecimalField diff --git a/saffier/core/db/models/model.py b/saffier/core/db/models/model.py index be6d82f..db40fa3 100644 --- a/saffier/core/db/models/model.py +++ b/saffier/core/db/models/model.py @@ -119,17 +119,8 @@ async def _save(self, **kwargs: typing.Any) -> "Model": saffier_setattr(self, self.pkname, awaitable) return self - async def _update(self, **kwargs: typing.Any) -> typing.Any: - """ - Performs the save instruction. - """ - pk_column = getattr(self.table.c, self.pkname) - expression = self.table.update().values(**kwargs).where(pk_column == self.pk) - awaitable = await self.database.execute(expression) - return awaitable - async def save( - self: typing.Any, + self, force_save: bool = False, values: typing.Any = None, **kwargs: typing.Any, @@ -162,7 +153,7 @@ async def save( await self._save(**kwargs) else: await self.signals.pre_update.send(sender=self.__class__, instance=self, kwargs=kwargs) - await self._update(**kwargs) + await self.update(**kwargs) await self.signals.post_update.send(sender=self.__class__, instance=self) # Refresh the results diff --git a/tests/models/test_datetime.py b/tests/models/test_datetime.py new file mode 100644 index 0000000..666b207 --- /dev/null +++ b/tests/models/test_datetime.py @@ -0,0 +1,66 @@ +import datetime +import time + +import pytest + +import saffier +from saffier.testclient import DatabaseTestClient as Database +from tests.settings import DATABASE_URL + +database = Database(url=DATABASE_URL) +models = saffier.Registry(database=database) + +pytestmark = pytest.mark.anyio + + +class User(saffier.Model): + name: str = saffier.CharField(max_length=255, secret=True) + created_at: datetime.datetime = saffier.DateTimeField(auto_now_add=True) + updated_at: datetime.datetime = saffier.DateTimeField(auto_now=True) + + class Meta: + registry = models + + +@pytest.fixture(autouse=True, scope="module") +async def create_test_database(): + await models.create_all() + yield + await models.drop_all() + + +@pytest.fixture(autouse=True) +async def rollback_transactions(): + with database.force_rollback(): + async with database: + yield + + +async def test_creates_and_updates_only_updated_at(): + user = await User.query.create(name="Test") + + last_created_datetime = user.created_at + last_updated_datetime = user.updated_at + + time.sleep(2) + + await user.update(name="Test 2") + + assert user.created_at == last_created_datetime + assert user.updated_at != last_updated_datetime + + +async def test_creates_and_updates_only_updated_at_on_save(): + user = await User.query.create(name="Test") + + last_created_datetime = user.created_at + last_updated_datetime = user.updated_at + + time.sleep(2) + + user.name = "Test 2" + await user.save() + + assert user.name == "Test 2" + assert user.created_at == last_created_datetime + assert user.updated_at != last_updated_datetime