Django
auto_now
auto_now_add
timestamp
DateTimeField

Django auto_now and auto_now_add

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Django gives DateTimeField two convenience options for automatic timestamps: auto_now and auto_now_add. They look similar, but they solve different problems, and using the wrong one can make a model harder to work with later.

What auto_now_add Does

auto_now_add=True sets the field once, when the object is first created. It is the usual choice for a created_at column because that value should represent the original insertion time.

python
1from django.db import models
2
3
4class Article(models.Model):
5    title = models.CharField(max_length=200)
6    created_at = models.DateTimeField(auto_now_add=True)

When a new Article is saved for the first time, Django fills created_at automatically. Later saves do not change it.

What auto_now Does

auto_now=True updates the field every time Django saves the model instance. That makes it a good fit for an updated_at field.

python
1from django.db import models
2
3
4class Article(models.Model):
5    title = models.CharField(max_length=200)
6    created_at = models.DateTimeField(auto_now_add=True)
7    updated_at = models.DateTimeField(auto_now=True)

With this model, updated_at changes on every save(), while created_at stays fixed.

Seeing the Difference in Practice

The following shell session shows the typical behavior:

python
1>>> article = Article.objects.create(title="First draft")
2>>> article.created_at
3datetime.datetime(...)
4>>> article.updated_at
5datetime.datetime(...)
6
7>>> article.title = "Published draft"
8>>> article.save()
9>>> article.created_at  # unchanged
10datetime.datetime(...)
11>>> article.updated_at  # refreshed
12datetime.datetime(...)

This distinction is the core rule: auto_now_add is for creation time, and auto_now is for last-modified time.

When default=timezone.now Is Better

These options are convenient, but they are not always flexible enough. If you want a timestamp that starts with the current time yet can still be edited later, use default=timezone.now instead.

python
1from django.db import models
2from django.utils import timezone
3
4
5class Event(models.Model):
6    starts_at = models.DateTimeField(default=timezone.now)

This gives the field an initial value without locking you into Django's automatic overwrite behavior. That matters for imported data, backfills, or admin workflows where a human needs to adjust the timestamp.

Important Behavior in Forms and Queries

Fields using auto_now and auto_now_add are not meant for user entry. In practice, Django treats them as managed fields, so they are excluded from normal form editing behavior.

Another important detail is that bulk updates do not call save() on each model instance. If you do this:

python
Article.objects.filter(published=True).update(title="Renamed")

Django sends a direct SQL update, so auto_now does not fire automatically. If you need a timestamp change during bulk operations, include it explicitly.

python
1from django.utils import timezone
2
3Article.objects.filter(published=True).update(
4    title="Renamed",
5    updated_at=timezone.now(),
6)

That behavior surprises many developers because instance saves and queryset updates do not go through the same path.

Time Zone Considerations

If USE_TZ is enabled, Django stores aware datetimes and converts them according to project settings. That is usually what you want. The key point is to stay consistent across your application so timestamp comparisons behave correctly.

For timestamps managed by Django, avoid mixing naive manual datetimes with timezone-aware values. Use timezone.now() when you need to set a value yourself.

Common Pitfalls

Using auto_now_add for an updated_at field is wrong because the value will never change after creation.

Using auto_now for a field that users should edit later is frustrating because Django overwrites it on every save.

Assuming QuerySet.update() triggers auto_now is a common mistake. It does not call model save().

Trying to import historical records with auto_now_add can be awkward because Django wants to manage the field automatically. Use a normal field with default=timezone.now when manual control matters.

Ignoring time zone settings can produce confusing comparisons and display bugs in multi-region systems.

Summary

  • 'auto_now_add sets a timestamp once at creation time.'
  • 'auto_now refreshes a timestamp on every model save.'
  • Use them for created_at and updated_at respectively.
  • Choose default=timezone.now when you need an editable initial timestamp.
  • Remember that bulk queryset updates bypass the automatic save() behavior.

Course illustration
Course illustration

All Rights Reserved.