summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSarah Boyce <42296566+sarahboyce@users.noreply.github.com>2024-08-05 21:36:49 +0200
committerNatalia <124304+nessita@users.noreply.github.com>2024-08-05 16:37:26 -0300
commit2ba4f4b0b550a98f10deac47c1bbddccbc7365cd (patch)
tree06d30b56e9c8d1c27dc886f72e3acd52cfdf7877
parentaed4ffe1897c51c0dfd8689c0834ca4ca0a8a03e (diff)
[5.1.x] Fixed #35657 -- Made FileField handle db_default values.
Backport of 8deb6bb1fc427762d56646bf7306cbd11fb5bb68 from main.
-rw-r--r--django/db/models/fields/files.py7
-rw-r--r--docs/releases/5.0.8.txt3
-rw-r--r--tests/file_storage/models.py3
-rw-r--r--tests/file_storage/tests.py14
4 files changed, 27 insertions, 0 deletions
diff --git a/django/db/models/fields/files.py b/django/db/models/fields/files.py
index 7c911f4b23..0716d3599e 100644
--- a/django/db/models/fields/files.py
+++ b/django/db/models/fields/files.py
@@ -9,6 +9,7 @@ from django.core.files.images import ImageFile
from django.core.files.storage import Storage, default_storage
from django.core.files.utils import validate_file_name
from django.db.models import signals
+from django.db.models.expressions import DatabaseDefault
from django.db.models.fields import Field
from django.db.models.query_utils import DeferredAttribute
from django.db.models.utils import AltersData
@@ -197,6 +198,12 @@ class FileDescriptor(DeferredAttribute):
attr = self.field.attr_class(instance, self.field, file)
instance.__dict__[self.field.attname] = attr
+ # If this value is a DatabaseDefault, initialize the attribute class
+ # for this field with its db_default value.
+ elif isinstance(file, DatabaseDefault):
+ attr = self.field.attr_class(instance, self.field, self.field.db_default)
+ instance.__dict__[self.field.attname] = attr
+
# Other types of files may be assigned as well, but they need to have
# the FieldFile interface added to them. Thus, we wrap any other type of
# File inside a FieldFile (well, the field's attr_class, which is
diff --git a/docs/releases/5.0.8.txt b/docs/releases/5.0.8.txt
index 5cc3faec98..704ecf2c61 100644
--- a/docs/releases/5.0.8.txt
+++ b/docs/releases/5.0.8.txt
@@ -32,3 +32,6 @@ Bugfixes
* Fixed a bug in Django 5.0 which caused constraint validation to either crash
or incorrectly raise validation errors for constraints referring to fields
using ``Field.db_default`` (:ticket:`35638`).
+
+* Fixed a crash in Django 5.0 when saving a model containing a ``FileField``
+ with a ``db_default`` set (:ticket:`35657`).
diff --git a/tests/file_storage/models.py b/tests/file_storage/models.py
index 873c3e176a..cb0207cae9 100644
--- a/tests/file_storage/models.py
+++ b/tests/file_storage/models.py
@@ -72,6 +72,9 @@ class Storage(models.Model):
default = models.FileField(
storage=temp_storage, upload_to="tests", default="tests/default.txt"
)
+ db_default = models.FileField(
+ storage=temp_storage, upload_to="tests", db_default="tests/db_default.txt"
+ )
empty = models.FileField(storage=temp_storage)
limited_length = models.FileField(
storage=temp_storage, upload_to="tests", max_length=20
diff --git a/tests/file_storage/tests.py b/tests/file_storage/tests.py
index 868b18dd2c..c7ca873521 100644
--- a/tests/file_storage/tests.py
+++ b/tests/file_storage/tests.py
@@ -944,6 +944,20 @@ class FileFieldStorageTests(TestCase):
self.assertEqual(obj.default.read(), b"default content")
obj.default.close()
+ def test_filefield_db_default(self):
+ temp_storage.save("tests/db_default.txt", ContentFile("default content"))
+ obj = Storage.objects.create()
+ self.assertEqual(obj.db_default.name, "tests/db_default.txt")
+ self.assertEqual(obj.db_default.read(), b"default content")
+ obj.db_default.close()
+
+ # File is not deleted, even if there are no more objects using it.
+ obj.delete()
+ s = Storage()
+ self.assertEqual(s.db_default.name, "tests/db_default.txt")
+ self.assertEqual(s.db_default.read(), b"default content")
+ s.db_default.close()
+
def test_empty_upload_to(self):
# upload_to can be empty, meaning it does not use subdirectory.
obj = Storage()