Ensure that auto_now=True fields gets updated on a update-query & add model.update_values(**) — Was: Handling modified_at (auto_now=True) with pydantic models
Hello!
How to update, for example (modified_at) field, using update model method. Example:
class User(Model):
id = fields.IntField(pk=True)
username = fields.CharField(max_length=50)
created_at = fields.DatetimeField(auto_now_add=True)
modified_at = fields.DatetimeField(auto_now=True)
UserUpdate_Pydantic = pydantic_model_creator(User, name="UserUpdate", exclude_readonly=True)```
user = UserUpdate_Pydantic(username='user_modified')
User.filter(id=user_id).update(**user.dict(exclude_unset=True))
That way, the modified_at field don't update because it is not pass to update model method
My question is: How can I update modified_at field implicitly
The modified_at updates when you do an instance.save().
But not for a filter().update()...
Yes, I see the issue. This is missing right now.
Either we need:
- A one-liner way to do a get, update_with_dict & save
- Or we handle
auto_now=Truefields as a special case, and always generate the value implicitly, even when doing an.update()operation?
Honestly, we might need both, as they fulfill different use-cases...
Point 1 would be used like so:
user_p = UserUpdate_Pydantic(username='user_modified')
user_m = User.get(id=user_id) # Get a single instance, or raise
user_m.update_values(**user.dict(exclude_unset=True)) # In-memory update of values.
user_m.save() # Persist entire model
Point 2, just like your example.
I can see use-cases for both, so I'm going to work on both.
Thanks for reporting this oversight.
I did the first item that is easier.
Please leave this ticket open for the .update() change, which is not quite as trivial to implement. I want to change that behaviour as the current one breaks the principle of least surprise.
You should be able to do:
user_p = UserUpdate_Pydantic(username='user_modified')
user_m = await User.get(id=user_id)
await user_m.update_from_dict(user.dict(exclude_unset=True)).save()
If you want to test it immediately you can do a:
pip install https://github.com/tortoise/tortoise-orm/archive/develop.zip
So quickly, thanks a lot!!!
@grigi no update on this? It's been 4 years.
models.User.create models.User.filter(id=user_id).update
I thought something like below would work, but still I get error.
AttributeError: type object 'Genre' has no attribute 'added_at'
class BaseModel(Model):
id = fields.IntField(pk=True)
added_at = fields.DatetimeField(auto_now_add=True)
modified_at = fields.DatetimeField(auto_now=True)
user = fields.ForeignKeyField(
model_name="models.User", on_delete=fields.SET_NULL, null=True
)
class Meta:
abstract = True
class PydanticMeta:
computed = ["added_at", "modified_at"]