I need to have modifed_at fields in my Django project. A field that updates every time a row updates in the database, despite where the update comes from: through calling .save()
or through queryset.update()
or even when updates happen in the database directly and not from the Django app.
there is an auto_now
property that does not solve my problem according to this SO question(based on Django document).
other SO questions(like this and this) ask the same thing, update instance at every change not only .save()
This problem can be solved using triggers as said here but this way we need to write the same trigger for every modifed_at field in models.
as discussed in this Django ticket this problem will not be addressed and solved in Django. even the suggested patch only updates the instance if it changes via Django.
the only way that comes to my mind is to do something like this in a mixin. a mixin that when inherited creates a trigger for fields with auto_now=True. maybe change SQL when Django creates the model creation SQL. but I don't know how to implement this.
so I have two questions:
- what is the best way to achieve database-level updates for modified_at fields
- If my suggested way is the best option how to implement it?
I would like to have a database-agnostic solution but FYI currently I'm using PostgreSQL.
CodePudding user response:
As you said, if you use triggers you'd have to create a trigger for every table.
To make this easier however you could create a migration file to create/destroy the trigger. Here's an example.
Then it would just be a matter of copy-pasting that migration file whenever you create a new model.
Edit:
You could even override the makemigrations
command to automatically add the creation of the trigger step to the operations of the initial migrations file. Here's an answer that shows how to override management commands.
CodePudding user response:
So you can use the Django's auto_now
field for that.
If you want to auto populate the DateTimeField when creating a new object you can do this: created_at = models.DateTimeField(auto_now_add=True, verbose_name=_("created_at"))
If you want to update the field anytime the object is updated you can do this instead: updated_at = models.DateTimeField(auto_now=True, verbose_name=_("updated at"))
For more info you can refer here