tortoise-orm
tortoise-orm copied to clipboard
save(force_update=True) error in specific cases
Describe the bug Use save(force_update=True) after getting an instance will cause an unexpected error
To Reproduce
from tortoise import Tortoise, fields, run_async
from tortoise.models import Model
class User(Model):
id: int = fields.IntField(pk=True)
name: str = fields.CharField(max_length=255)
async def main():
await Tortoise.init(db_url="mysql://test@localhost/test", modules={"models": ["__main__"]})
await Tortoise.generate_schemas()
# create a user, not important here
await User.create(name='111')
user = await User.get(id=1)
user.update_from_dict(dict(name='222'))
await user.save(force_update=True) # raise exception
if __name__ == '__main__':
run_async(main())
File "/app/tortoise-bug/.venv/lib/python3.10/site-packages/tortoise/models.py", line 948, in save
raise IntegrityError(f"Can't update object that doesn't exist. PK: {self.pk}")
tortoise.exceptions.IntegrityError: Can't update object that doesn't exist. PK: 1
Expected behavior Should working
Additional context
# my test environment
python version: 3.10
tortoise-orm version: 0.18.1 and 0.19.2
mysql: mariadb 10.8.3 and mysql 5.8 (GCP)
- DB engine uses the sample sqlite without error
--- await Tortoise.init(db_url="mysql://test@localhost/test", modules={"models": ["__main__"]})
+++ await Tortoise.init(db_url="sqlite://:memory:", modules={"models": ["__main__"]})
- The instance is not from get will without error
--- await User.create(name='111')
--- user = await User.get(id=1)
+++ user = await User.create(name='111')
- save method does not use the force_update parameter without error
--- await user.save(force_update=True) # raise exception
+++ await user.save()
in "/home/shonen/tortoise-bug/.venv/lib/python3.10/site-packages/tortoise/models.py", line 948
elif force_update:
rows = await executor.execute_update(self, update_fields)
# my test
assert rows==1, f'{rows=} {type(rows)=}'
if rows == 0:
raise IntegrityError(f"Can't update object that doesn't exist. PK: {self.pk}")
created = False
AssertionError: rows=0 type(rows)=<class 'int'>
In addition, an unbelievable result occurred in my company's environment (with FastAPI) (but not successfully reproduced in the minimal example)
elif force_update:
rows = await executor.execute_update(self, update_fields)
# my test
assert rows==1, f'{rows=} {type(rows)=}'
raise Exception(f'{rows=} {type(rows)=}')
if rows == 0:
raise IntegrityError(f"Can't update object that doesn't exist. PK: {self.pk}")
created = False
File "/app/tortoise-bug/.venv/lib/python3.10/site-packages/tortoise/models.py", line 944, in save
raise Exception(f'{rows=} {type(rows)=}')
Exception: rows=1 type(rows)=<class 'int'>