Fixed #27334 -- Allowed FileField to move rather than copy a file.

When a FileField is set to an instance of File that is not also an
instance of FieldFile, pre_save() passes that object as the contents to
Storage.save(). This allows the file to be moved rather than copied
to the upload destination.
This commit is contained in:
Adam Chidlow 2016-10-14 11:13:43 +08:00 committed by Tim Graham
parent 7cdc2015e3
commit f734e2d4b2
2 changed files with 21 additions and 2 deletions

View File

@ -293,7 +293,7 @@ class FileField(Field):
file = super(FileField, self).pre_save(model_instance, add) file = super(FileField, self).pre_save(model_instance, add)
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, save=False) file.save(file.name, file.file, save=False)
return file return file
def contribute_to_class(self, cls, name, **kwargs): def contribute_to_class(self, cls, name, **kwargs):

View File

@ -1,4 +1,10 @@
from django.test import TestCase import os
import sys
import unittest
from django.core.files import temp
from django.core.files.uploadedfile import TemporaryUploadedFile
from django.test import TestCase, override_settings
from .models import Document from .models import Document
@ -54,3 +60,16 @@ class FileFieldTests(TestCase):
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')
@unittest.skipIf(sys.platform.startswith('win'), "Windows doesn't support moving open files.")
# The file's source and destination must be on the same filesystem.
@override_settings(MEDIA_ROOT=temp.gettempdir())
def test_move_temporary_file(self):
"""
The temporary uploaded file is moved rather than copied to the
destination.
"""
with TemporaryUploadedFile('something.txt', 'text/plain', 0, 'UTF-8') as tmp_file:
tmp_file_path = tmp_file.temporary_file_path()
Document.objects.create(myfile=tmp_file)
self.assertFalse(os.path.exists(tmp_file_path), 'Temporary file still exists')