{
  "id": 19998695,
  "title": "Django: Use auto_now and auto_now_add Correctly — When to Switch to default=timezone.now",
  "url": "https://urgent.news/2026/11/14/django-use-auto-now-and-auto-now-add-correctly-when-to-switch-to",
  "topic": "tech",
  "section": "Tech",
  "published": "2026-11-14T15:13:07.000Z",
  "source": {
    "name": "Dev.to",
    "slug": "dev-to",
    "url": "https://dev.to/linhfishdev/django-use-autonow-and-autonowadd-correctly-when-to-switch-to-defaulttimezonenow-582k"
  },
  "original_language": "en",
  "account": "Django models commonly include two timestamp fields: created_at to indicate when a record was generated, and updated_at for the most recent modification. The simplest method is utilizing auto_now_add=True for created_at and auto_now=True for updated_at, with Django automatically populating both values. However, there are three typical pitfalls to be aware of.\n\nWhen importing 500 previous blog posts and wishing to preserve their initial publication dates, creating a Post object with a predetermined created_at value does not retain the original date. This happens because auto_now_add only executes during the creation process, overwriting any values passed during the create() operation with timezone.now().\n\nA second issue arises during bulk updates. Altering the status of 1,000 posts to published doesn't update the updated_at field of all posts. This is due to QuerySet.update() running SQL directly, bypassing the save() method, so auto_now doesn't trigger. Consequently, users viewing the last updated timestamp will see an outdated date despite the content having changed.\n\nTo maintain the original date during import, instead of using auto_now_add for created_at, use default=timezone.now. This default assigns the current time through the function, rather than calling it. This approach allows for creating records without specifying created_at, importing old dates, and keeping them editable in the admin and ModelForm.\n\nFor bulk updates, explicitly pass updated_at using timezone.now() to ensure it is updated. If you prefer to retain auto_now_add because you rarely modify created_at, you can still do so by creating the record first, assigning created_at afterward, and saving again. This works because auto_now_add only runs on INSERT operations.\n\nIn summary, apply auto_now_add/auto_now to tables where only a timestamp is needed, like logs or posts whose dates you never edit. For business data such as post publish dates, expiry dates, or event start dates that you may need to edit manually, import old data, or let users change in the admin, use default=timezone.now. Always verify that updated_at is updated after every QuerySet.update() or bulk_update() operation to prevent outdated timestamps.",
  "summary": "Most Django models have two timestamp fields: created_at to know when a record was created and updated_at for the last edit. The quickest way is auto_now_add=True for created_at and auto_now=True for updated_at — Django fills in both and you never touch them. But these two options have three common \"traps\": you can't assign an old date when importing data, bulk update() doesn't change updated_at,…",
  "key_points": [
    "Use autonowadd for initial creation dates, not for updating existing records",
    "Pass updatedat explicitly during bulk updates to ensure it's current",
    "Default=timezone.now preserves original dates during imports"
  ],
  "editors_take": null,
  "illustration": null,
  "coverage": {
    "outlets": 1,
    "also_reported_by": []
  },
  "ai_generated": true,
  "disclaimer": "Summaries, key points and the editor’s take are written by software from other outlets’ reporting and may contain errors — always check the linked original."
}