mirror of https://github.com/django/django.git
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.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.storage import Storage, default_storage
|
||||
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.utils import AltersData
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.utils.version import PY311
|
||||
|
||||
|
||||
class FieldFile(File, AltersData):
|
||||
|
@ -312,6 +314,15 @@ class FileField(Field):
|
|||
|
||||
def pre_save(self, 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:
|
||||
# Commit the file to storage prior to saving the model
|
||||
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.
|
||||
|
||||
* :class:`~django.db.models.FileField` now raises a
|
||||
:class:`~django.core.exceptions.FieldError` when saving a file without a
|
||||
``name``.
|
||||
|
||||
.. _deprecated-features-5.1:
|
||||
|
||||
Features deprecated in 5.1
|
||||
|
|
|
@ -5,13 +5,14 @@ import tempfile
|
|||
import unittest
|
||||
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.base import ContentFile
|
||||
from django.core.files.uploadedfile import TemporaryUploadedFile
|
||||
from django.db import IntegrityError, models
|
||||
from django.test import TestCase, override_settings
|
||||
from django.test.utils import isolate_apps
|
||||
from django.utils.version import PY311
|
||||
|
||||
from .models import Document
|
||||
|
||||
|
@ -72,6 +73,27 @@ class FileFieldTests(TestCase):
|
|||
with self.assertRaisesMessage(SuspiciousFileOperation, msg):
|
||||
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):
|
||||
Document.objects.create(myfile="something.txt")
|
||||
self.assertEqual(Document.objects.defer("myfile")[0].myfile, "something.txt")
|
||||
|
|
Loading…
Reference in New Issue