Django Manual Editing Auto DateTime Fields
TL;DR: use default=timezone.now, editable=False, blank=True
to mimic the behavior of auto_now
and auto_now_add
.
Django's auto_now
and auto_now_add
fields are built-in django model fields and used to track when a model was modified or created. They are suppose to be readonly fields. But there are times that I want to overwrite these two fields for some model instances. For example: I'd like to change my test data to match exact timestamp each time.
Models' auto_now
and auto_now_add
will set the field to have editable=False
and blank=True
.
from django.utils import timezoneclass MyModel(models.Model): createdAt = models.DateTimeField(default=timezone.now, editable=False, blank=True) lastUpdatedAt = models.DateTimeField(default=timezone.now, editable=False, blank=True)
By passing
timezone.now
without parentheses as the default value ofDateTimeField
, this function will be called each time a record is added. If, instead,timezone.now()
was passed, the return value oftimezone.now()
will be used when the model is defined, not each time adding a record.
Temporarily disable auto_now
and auto_now_add
attributes
We can achieve this by changing model fields' attribute
model_instance = MyModel()for field in model_instance._meta.get_fields(): if field.name == 'createdAt': field.auto_now = False elif field.name == 'lastUpdatedAt': field.auto_now_add = Falsemodel_instance.createAt = timezone.now()model_instance.lastUpdatedAt = timezone.now()for field in model_instance._meta.get_fields(): if field.name == 'createdAt': field.auto_now = True elif field.name == 'lastUpdatedAt': field.auto_now_add = True
Use SQL update statement to bypass Django's save()
mechanism
Both auto_now
and auto_now_add
are relies on Django models' save()
mechanism and thus we can use update()
to bypass it.
MyModel.objects.filter(id=<instance_id>).update(createdAt=timezone.now())