Repository: django/django

Issue:
# Fixed #36847 -- Ensured auto_now_add fields are set before FileField.upload_to is called.

#### Trac ticket number
<!-- Replace XXXXX with the corresponding Trac ticket number. -->
<!-- Or delete the line and write "N/A" if this is a trivial PR. -->

ticket-36847

#### Branch description
In Django 5.2 and earlier, an `auto_now_add=True` `DateTimeField` could be accessed inside a `FileField`’s `upload_to` callable, because the field was populated with the current timestamp during insertion.
This is a regression introduced in 94680437a45a71c70ca8bd2e68b72aa1e2eff337 where the insert path called `field.pre_save()` with `add=False` instead of `add=True`. 

This fix restores the correct behavior by changing the argument back to `add=True`.
(Used AI to help create the test coverage for the fix. I have verified that it's working correctly.)

#### AI Assistance Disclosure (REQUIRED)
<!-- Please select exactly ONE of the following: -->
- [ ] **No AI tools were used** in preparing this PR.
- [x] **If AI tools were used**, I have disclosed which ones, and fully reviewed and verified their output.

#### Checklist
- [x] This PR follows the [contribution guidelines](https://docs.djangoproject.com/en/stable/internals/contributing/writing-code/submitting-patches/).
- [x] This PR **does not** disclose a security vulnerability (see [vulnerability reporting](https://docs.djangoproject.com/en/stable/internals/security/)).
- [x] This PR targets the `main` branch. <!-- Backports will be evaluated and done by mergers, when necessary. -->
- [x] The commit message is written in past tense, mentions the ticket number, and ends with a period.
- [x] I have checked the "Has patch" ticket flag in the Trac system.
- [x] I have added or updated relevant tests.
- [x] I have added or updated relevant docs, including release notes if applicable.
- [ ] I have attached screenshots in both light and dark modes for any UI changes.


Implementation patch:
diff --git a/django/db/models/base.py b/django/db/models/base.py
index ad3f0c5e23a1..d53da600d792 100644
--- a/django/db/models/base.py
+++ b/django/db/models/base.py
@@ -1175,7 +1175,9 @@ def _save_table(
             ].features.can_return_columns_from_insert
             for field in insert_fields:
                 value = (
-                    getattr(self, field.attname) if raw else field.pre_save(self, False)
+                    getattr(self, field.attname)
+                    if raw
+                    else field.pre_save(self, add=True)
                 )
                 if hasattr(value, "resolve_expression"):
                     if field not in returning_fields:


Test patch:
diff --git a/tests/model_fields/models.py b/tests/model_fields/models.py
index 1d8a447dee8b..a594b89adb0d 100644
--- a/tests/model_fields/models.py
+++ b/tests/model_fields/models.py
@@ -262,10 +262,20 @@ class DataModel(models.Model):
 # FileField
 
 
+def upload_to_with_date(instance, filename):
+    return f"{instance.created_at.year}/{filename}"
+
+
 class Document(models.Model):
     myfile = models.FileField(storage=temp_storage, upload_to="unused", unique=True)
 
 
+# See ticket #36847.
+class DocumentWithTimestamp(models.Model):
+    created_at = models.DateTimeField(auto_now_add=True)
+    myfile = models.FileField(storage=temp_storage, upload_to=upload_to_with_date)
+
+
 ###############################################################################
 # ImageField
 
diff --git a/tests/model_fields/test_filefield.py b/tests/model_fields/test_filefield.py
index 57cc7365da15..fbf5c837ac57 100644
--- a/tests/model_fields/test_filefield.py
+++ b/tests/model_fields/test_filefield.py
@@ -13,7 +13,7 @@
 from django.test import TestCase, override_settings
 from django.test.utils import isolate_apps
 
-from .models import Document
+from .models import Document, DocumentWithTimestamp
 
 
 class FileFieldTests(TestCase):
@@ -209,3 +209,9 @@ class MyDocument(AbstractMyDocument):
 
         document = MyDocument(myfile="test_file.py")
         self.assertEqual(document.myfile.field.model, MyDocument)
+
+    def test_upload_to_callable_sees_auto_now_add_field_value(self):
+        d = DocumentWithTimestamp(myfile=ContentFile(b"content", name="foo"))
+        d.save()
+        self.assertIsNotNone(d.created_at)
+        self.assertIs(d.myfile.name.startswith(f"{d.created_at.year}/foo"), True)