There are several ways and it depends a lot on what your goal is and how you want to implement it:
Implement an abstract class for auditing:
You can write an abstract class that has your audit fields, and the table will be created automatically with those fields, that is.
created_at = models.DateTimeField(auto_now_add=True)
created_by = models.CharField(max_length=255, blank=True, editable=False)
modified_at = models.DateTimeField(auto_now=True)
modified_by = models.CharField(max_length=255, blank=True, editable=False)
abstract = True
Create a signal that captures the saved and deleted events and registers them in a table.
name = models.CharField(max_length=255)
The advantage of using this form is that it is not intrusive, you do not have to modify the models to use it, the disadvantage is that you can not customize some extra parameters, like the user you are modifying.
def audit(sender, **kwargs):
obj_str = str(kwargs.get('instance'))
Auditoria(instancia = obj_str, accion="guardado").save()
You can copy the snippet from link and use it to save an audit field for any model.
Use an external library to audit and save history:
from django.db import models
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
salary = models.PositiveIntegerField()
history = audit.AuditTrail()
Finally you can use any of the applications that the django packages universe offers: link