Django

Code

Changeset 8007

Show
Ignore:
Timestamp:
07/20/08 07:44:41 (4 months ago)
Author:
russellm
Message:

Fixed #6450 -- Improved the checking of errors when creating the directories for saved files. Thanks to henry@precheur.org for the report and patch, and vung for the excellent test case.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/trunk/django/db/models/base.py

    r7998 r8007  
    473473 
    474474    def _save_FIELD_file(self, field, filename, raw_field, save=True): 
    475         directory = field.get_directory_name() 
    476         try: # Create the date-based directory if it doesn't exist. 
    477             os.makedirs(os.path.join(settings.MEDIA_ROOT, directory)) 
    478         except OSError: # Directory probably already exists. 
    479             pass 
     475        # Create the upload directory if it doesn't already exist 
     476        directory = os.path.join(settings.MEDIA_ROOT, field.get_directory_name()) 
     477        if not os.path.exists(directory): 
     478            os.makedirs(directory) 
     479        elif not os.path.isdir(directory): 
     480            raise IOError('%s exists and is not a directory' % directory)         
    480481 
    481482        # Check for old-style usage (files-as-dictionaries). Warn here first 
  • django/trunk/tests/regressiontests/file_uploads/models.py

    r7814 r8007  
    1 # This file unintentionally left blank. 
    2 # Oops. 
     1import tempfile 
     2import os 
     3from django.db import models 
     4 
     5UPLOAD_ROOT = tempfile.mkdtemp() 
     6UPLOAD_TO = os.path.join(UPLOAD_ROOT, 'test_upload') 
     7 
     8class FileModel(models.Model): 
     9    testfile = models.FileField(upload_to=UPLOAD_TO) 
  • django/trunk/tests/regressiontests/file_uploads/tests.py

    r7904 r8007  
    11import os 
     2import errno 
    23import sha 
     4import shutil 
    35import tempfile 
     6import unittest 
     7 
     8from django.core.files.uploadedfile import SimpleUploadedFile 
    49from django.test import TestCase, client 
    510from django.utils import simplejson 
     11 
     12from models import FileModel, UPLOAD_ROOT, UPLOAD_TO 
    613 
    714class FileUploadTests(TestCase): 
     
    180187        self.assertEqual(got.get('file1'), 1) 
    181188        self.assertEqual(got.get('file2'), 2) 
     189 
     190class DirectoryCreationTests(unittest.TestCase): 
     191    """ 
     192    Tests for error handling during directory creation  
     193    via _save_FIELD_file (ticket #6450) 
     194    """ 
     195    def setUp(self): 
     196        self.obj = FileModel() 
     197        if not os.path.isdir(UPLOAD_ROOT): 
     198            os.makedirs(UPLOAD_ROOT) 
     199 
     200    def tearDown(self): 
     201        os.chmod(UPLOAD_ROOT, 0700) 
     202        shutil.rmtree(UPLOAD_ROOT) 
     203 
     204    def test_readonly_root(self): 
     205        """Permission errors are not swallowed""" 
     206        os.chmod(UPLOAD_ROOT, 0500) 
     207        try: 
     208            self.obj.save_testfile_file('foo.txt', SimpleUploadedFile('foo.txt', 'x')) 
     209        except OSError, err: 
     210            self.assertEquals(err.errno, errno.EACCES) 
     211        except: 
     212            self.fail("OSError [Errno %s] not raised" % errno.EACCES) 
     213 
     214    def test_not_a_directory(self): 
     215        """The correct IOError is raised when the upload directory name exists but isn't a directory""" 
     216        # Create a file with the upload directory name 
     217        fd = open(UPLOAD_TO, 'w') 
     218        fd.close() 
     219        try: 
     220            self.obj.save_testfile_file('foo.txt', SimpleUploadedFile('foo.txt', 'x')) 
     221        except IOError, err: 
     222            # The test needs to be done on a specific string as IOError 
     223            # is raised even without the patch (just not early enough) 
     224            self.assertEquals(err.args[0],  
     225                              "%s exists and is not a directory" % UPLOAD_TO) 
     226        except: 
     227            self.fail("IOError not raised")