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 timezone
class 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 of DateTimeField, this function will be called each time a record is added. If, instead, timezone.now() was passed, the return value of timezone.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 = False
model_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())