mirror of
https://github.com/django/django.git
synced 2025-01-03 06:55:47 +00:00
Fixed #35384 -- Raised FieldError when saving a file without a name to FileField.
This commit is contained in:
parent
b691accea1
commit
c0b0ce85ed
@ -3,7 +3,8 @@ import posixpath
|
|||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.core import checks
|
from django.core import checks
|
||||||
from django.core.files.base import File
|
from django.core.exceptions import FieldError
|
||||||
|
from django.core.files.base import ContentFile, File
|
||||||
from django.core.files.images import ImageFile
|
from django.core.files.images import ImageFile
|
||||||
from django.core.files.storage import Storage, default_storage
|
from django.core.files.storage import Storage, default_storage
|
||||||
from django.core.files.utils import validate_file_name
|
from django.core.files.utils import validate_file_name
|
||||||
@ -12,6 +13,7 @@ from django.db.models.fields import Field
|
|||||||
from django.db.models.query_utils import DeferredAttribute
|
from django.db.models.query_utils import DeferredAttribute
|
||||||
from django.db.models.utils import AltersData
|
from django.db.models.utils import AltersData
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
from django.utils.version import PY311
|
||||||
|
|
||||||
|
|
||||||
class FieldFile(File, AltersData):
|
class FieldFile(File, AltersData):
|
||||||
@ -312,6 +314,15 @@ class FileField(Field):
|
|||||||
|
|
||||||
def pre_save(self, model_instance, add):
|
def pre_save(self, model_instance, add):
|
||||||
file = super().pre_save(model_instance, add)
|
file = super().pre_save(model_instance, add)
|
||||||
|
if file.name is None and file._file is not None:
|
||||||
|
exc = FieldError(
|
||||||
|
f"File for {self.name} must have "
|
||||||
|
"the name attribute specified to be saved."
|
||||||
|
)
|
||||||
|
if PY311 and isinstance(file._file, ContentFile):
|
||||||
|
exc.add_note("Pass a 'name' argument to ContentFile.")
|
||||||
|
raise exc
|
||||||
|
|
||||||
if file and not file._committed:
|
if file and not file._committed:
|
||||||
# Commit the file to storage prior to saving the model
|
# Commit the file to storage prior to saving the model
|
||||||
file.save(file.name, file.file, save=False)
|
file.save(file.name, file.file, save=False)
|
||||||
|
@ -425,6 +425,10 @@ Miscellaneous
|
|||||||
|
|
||||||
* The minimum supported version of SQLite is increased from 3.27.0 to 3.31.0.
|
* The minimum supported version of SQLite is increased from 3.27.0 to 3.31.0.
|
||||||
|
|
||||||
|
* :class:`~django.db.models.FileField` now raises a
|
||||||
|
:class:`~django.core.exceptions.FieldError` when saving a file without a
|
||||||
|
``name``.
|
||||||
|
|
||||||
.. _deprecated-features-5.1:
|
.. _deprecated-features-5.1:
|
||||||
|
|
||||||
Features deprecated in 5.1
|
Features deprecated in 5.1
|
||||||
|
@ -5,13 +5,14 @@ import tempfile
|
|||||||
import unittest
|
import unittest
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from django.core.exceptions import SuspiciousFileOperation
|
from django.core.exceptions import FieldError, SuspiciousFileOperation
|
||||||
from django.core.files import File, temp
|
from django.core.files import File, temp
|
||||||
from django.core.files.base import ContentFile
|
from django.core.files.base import ContentFile
|
||||||
from django.core.files.uploadedfile import TemporaryUploadedFile
|
from django.core.files.uploadedfile import TemporaryUploadedFile
|
||||||
from django.db import IntegrityError, models
|
from django.db import IntegrityError, models
|
||||||
from django.test import TestCase, override_settings
|
from django.test import TestCase, override_settings
|
||||||
from django.test.utils import isolate_apps
|
from django.test.utils import isolate_apps
|
||||||
|
from django.utils.version import PY311
|
||||||
|
|
||||||
from .models import Document
|
from .models import Document
|
||||||
|
|
||||||
@ -72,6 +73,27 @@ class FileFieldTests(TestCase):
|
|||||||
with self.assertRaisesMessage(SuspiciousFileOperation, msg):
|
with self.assertRaisesMessage(SuspiciousFileOperation, msg):
|
||||||
document.save()
|
document.save()
|
||||||
|
|
||||||
|
def test_save_content_file_without_name(self):
|
||||||
|
d = Document()
|
||||||
|
d.myfile = ContentFile(b"")
|
||||||
|
msg = "File for myfile must have the name attribute specified to be saved."
|
||||||
|
with self.assertRaisesMessage(FieldError, msg) as cm:
|
||||||
|
d.save()
|
||||||
|
|
||||||
|
if PY311:
|
||||||
|
self.assertEqual(
|
||||||
|
cm.exception.__notes__, ["Pass a 'name' argument to ContentFile."]
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_delete_content_file(self):
|
||||||
|
file = ContentFile(b"", name="foo")
|
||||||
|
d = Document.objects.create(myfile=file)
|
||||||
|
d.myfile.delete()
|
||||||
|
self.assertIsNone(d.myfile.name)
|
||||||
|
msg = "The 'myfile' attribute has no file associated with it."
|
||||||
|
with self.assertRaisesMessage(ValueError, msg):
|
||||||
|
getattr(d.myfile, "file")
|
||||||
|
|
||||||
def test_defer(self):
|
def test_defer(self):
|
||||||
Document.objects.create(myfile="something.txt")
|
Document.objects.create(myfile="something.txt")
|
||||||
self.assertEqual(Document.objects.defer("myfile")[0].myfile, "something.txt")
|
self.assertEqual(Document.objects.defer("myfile")[0].myfile, "something.txt")
|
||||||
|
Loading…
Reference in New Issue
Block a user