mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Fixed #35384 -- Raised FieldError when saving a file without a name to FileField.
This commit is contained in:
		| @@ -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") | ||||
|   | ||||
		Reference in New Issue
	
	Block a user