From 1e73a06ba014372244eb2c8e04a0779ff28d44bd Mon Sep 17 00:00:00 2001
From: Nick Sweeting <git@sweeting.me>
Date: Wed, 28 Aug 2024 03:02:37 -0700
Subject: [PATCH] change ABIDModel.created to use AutoTimeField seeded on .save
 instead of auto_now_add so that ts_src for ABID is available on creation
 before DB row is created

---
 archivebox/abid_utils/models.py               | 10 +++++-
 ...t_created_alter_snapshot_added_and_more.py | 35 +++++++++++++++++++
 archivebox/core/models.py                     |  8 ++---
 3 files changed, 48 insertions(+), 5 deletions(-)
 create mode 100644 archivebox/core/migrations/0069_alter_archiveresult_created_alter_snapshot_added_and_more.py

diff --git a/archivebox/abid_utils/models.py b/archivebox/abid_utils/models.py
index c62f7208..4e25ac0a 100644
--- a/archivebox/abid_utils/models.py
+++ b/archivebox/abid_utils/models.py
@@ -61,6 +61,11 @@ def get_or_create_system_user_pk(username='system'):
     return user.pk
 
 
+class AutoDateTimeField(models.DateTimeField):
+    def pre_save(self, model_instance, add):
+        return timezone.now()
+
+
 class ABIDModel(models.Model):
     """
     Abstract Base Model for other models to depend on. Provides ArchiveBox ID (ABID) interface.
@@ -76,13 +81,16 @@ class ABIDModel(models.Model):
     abid = ABIDField(prefix=abid_prefix)
 
     created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, default=get_or_create_system_user_pk)
-    created = models.DateTimeField(auto_now_add=True)
+    created = AutoDateTimeField(default=timezone.now, db_index=True)
     modified = models.DateTimeField(auto_now=True)
 
     class Meta(TypedModelMeta):
         abstract = True
 
     def save(self, *args: Any, **kwargs: Any) -> None:
+        if self._state.adding or not self.created:
+            self.created = timezone.now()
+
         # when first creating a row, self.ABID is the source of truth
         # overwrite default prefilled self.id & self.abid with generated self.ABID value
         if self._state.adding or not self.id:
diff --git a/archivebox/core/migrations/0069_alter_archiveresult_created_alter_snapshot_added_and_more.py b/archivebox/core/migrations/0069_alter_archiveresult_created_alter_snapshot_added_and_more.py
new file mode 100644
index 00000000..fcc9b0aa
--- /dev/null
+++ b/archivebox/core/migrations/0069_alter_archiveresult_created_alter_snapshot_added_and_more.py
@@ -0,0 +1,35 @@
+# Generated by Django 5.1 on 2024-08-28 09:40
+
+import abid_utils.models
+import django.utils.timezone
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0068_alter_archiveresult_options'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='archiveresult',
+            name='created',
+            field=abid_utils.models.AutoDateTimeField(db_index=True, default=django.utils.timezone.now),
+        ),
+        migrations.AlterField(
+            model_name='snapshot',
+            name='added',
+            field=abid_utils.models.AutoDateTimeField(db_index=True, default=django.utils.timezone.now),
+        ),
+        migrations.AlterField(
+            model_name='snapshot',
+            name='created',
+            field=abid_utils.models.AutoDateTimeField(db_index=True, default=django.utils.timezone.now),
+        ),
+        migrations.AlterField(
+            model_name='tag',
+            name='created',
+            field=abid_utils.models.AutoDateTimeField(db_index=True, default=django.utils.timezone.now),
+        ),
+    ]
diff --git a/archivebox/core/models.py b/archivebox/core/models.py
index bf2c1fec..a362bdae 100644
--- a/archivebox/core/models.py
+++ b/archivebox/core/models.py
@@ -12,6 +12,7 @@ from uuid import uuid4
 from pathlib import Path
 
 from django.db import models
+from django.utils import timezone
 from django.utils.functional import cached_property
 from django.utils.text import slugify
 from django.core.cache import cache
@@ -19,7 +20,7 @@ from django.urls import reverse, reverse_lazy
 from django.db.models import Case, When, Value, IntegerField
 from django.conf import settings
 
-from abid_utils.models import ABIDModel, ABIDField
+from abid_utils.models import ABIDModel, ABIDField, AutoDateTimeField
 
 from ..system import get_dir_size
 from ..util import parse_date, base_url
@@ -50,7 +51,7 @@ class Tag(ABIDModel):
     Based on django-taggit model + ABID base.
     """
     abid_prefix = 'tag_'
-    abid_ts_src = 'self.created'          # TODO: add created/modified time
+    abid_ts_src = 'self.created'
     abid_uri_src = 'self.slug'
     abid_subtype_src = '"03"'
     abid_rand_src = 'self.old_id'
@@ -60,7 +61,6 @@ class Tag(ABIDModel):
     id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, unique=True)
     abid = ABIDField(prefix=abid_prefix)
 
-
     name = models.CharField(unique=True, blank=False, max_length=100)
     slug = models.SlugField(unique=True, blank=False, max_length=100, editable=False)
     # slug is autoset on save from name, never set it manually
@@ -149,7 +149,7 @@ class Snapshot(ABIDModel):
     
     tags = models.ManyToManyField(Tag, blank=True, through=SnapshotTag, related_name='snapshot_set', through_fields=('snapshot', 'tag'))
 
-    added = models.DateTimeField(auto_now_add=True, db_index=True)
+    added = AutoDateTimeField(default=timezone.now, db_index=True)
     updated = models.DateTimeField(auto_now=True, blank=True, null=True, db_index=True)
 
     keys = ('url', 'timestamp', 'title', 'tags', 'updated')