Ticket #4948: safe_filename_gen.1.diff

File safe_filename_gen.1.diff, 6.5 KB (added by Robert Coup, 17 years ago)

Been doing this too long...

  • django/db/models/base.py

     
    380380            pass
    381381        filename = field.get_filename(filename)
    382382
    383         # If the filename already exists, keep adding an underscore to the name of
    384         # the file until the filename doesn't exist.
    385         while os.path.exists(os.path.join(settings.MEDIA_ROOT, filename)):
     383        # Generate a unique filename
     384        while True:
     385            full_filename = os.path.join(settings.MEDIA_ROOT, filename)
    386386            try:
     387                # Try and open our filename, but only if it doesn't exist
     388                # and we can open it exclusively. This won't necessarily work on
     389                # NFS and some other networked filesystems, but will be ok in normal
     390                # cases.
     391                fd = os.open(full_filename, os.O_RDWR | os.O_CREAT | os.O_EXCL)
     392                break;
     393            except OSError, e:
     394                # Someone else grabbed this name already
     395                pass
     396
     397            # If the filename already exists, keep adding an underscore to the name of
     398            # the file until the filename doesn't exist.
     399            try:
    387400                dot_index = filename.rindex('.')
    388401            except ValueError: # filename has no dot
    389402                filename += '_'
     
    393406        # Write the file to disk.
    394407        setattr(self, field.attname, filename)
    395408
    396         full_filename = self._get_FIELD_filename(field)
    397         fp = open(full_filename, 'wb')
     409        fp = os.fdopen(fd, 'w+b')
    398410        fp.write(raw_contents)
    399411        fp.close()
    400412
  • tests/regressiontests/file_field/tests.py

     
    11"""
    2 Tests for file field behavior, and specifically #639, in which Model.save() gets
    3 called *again* for each FileField. This test will fail if calling an
    4 auto-manipulator's save() method causes Model.save() to be called more than once.
     2Tests for file field behavior.
    53"""
    6 
     4import tempfile
    75import os
     6import shutil
    87import unittest
    9 from regressiontests.bug639.models import Photo
     8from regressiontests.file_field.models import Photo
    109from django.http import QueryDict
    1110from django.utils.datastructures import MultiValueDict
     11from django.conf import settings
    1212
    13 class Bug639Test(unittest.TestCase):
    14        
     13class FileFieldTests(unittest.TestCase):
     14    def setUp(self):
     15        self.img_content = open(os.path.join(os.path.dirname(__file__), "test.jpg"), "rb").read()
     16        self.old_media_root = settings.MEDIA_ROOT
     17        settings.MEDIA_ROOT = tempfile.gettempdir()
     18   
    1519    def testBug639(self):
    1620        """
    1721        Simulate a file upload and check how many times Model.save() gets called.
     22       
     23        #639, in which Model.save() gets called *again* for each FileField. This
     24        test will fail if calling an auto-manipulator's save() method causes
     25        Model.save() to be called more than once.
    1826        """
    1927        # Grab an image for testing
    20         img = open(os.path.join(os.path.dirname(__file__), "test.jpg"), "rb").read()
    2128       
    2229        # Fake a request query dict with the file
    2330        qd = QueryDict("title=Testing&image=", mutable=True)
    2431        qd["image_file"] = {
    2532            "filename" : "test.jpg",
    2633            "content-type" : "image/jpeg",
    27             "content" : img
     34            "content" : self.img_content
    2835        }
    2936       
    3037        manip = Photo.AddManipulator()
     
    3441        # Check the savecount stored on the object (see the model)
    3542        self.assertEqual(p._savecount, 1)
    3643       
     44    def testFilenameGeneration_unique(self):
     45        """
     46        Make sure we're generating unique filenames.
     47        Note that upload_to is set to 'file_field_test'
     48        """
     49       
     50        p0 = Photo(title="test0")
     51        p0.save_image_file('testfg0.jpg', self.img_content)
     52        self.assert_(os.path.exists(p0.get_image_filename()))
     53        self.assertEqual(p0.image, "file_field_test/testfg0.jpg")
     54        # Second file should have an '_' before the extension
     55        p1 = Photo(title="test1")
     56        p1.save_image_file('testfg0.jpg', self.img_content)
     57        self.assert_(os.path.exists(p1.get_image_filename()))
     58        self.assertNotEqual(p0.image, p1.image)
     59        self.assertEqual(p1.image, "file_field_test/testfg0_.jpg")
     60       
     61        # Now test with no extension
     62        p2 = Photo(title="test2")
     63        p2.save_image_file('testfg1', self.img_content)
     64        self.assert_(os.path.exists(p2.get_image_filename()))
     65        self.assertEqual(p2.image, "file_field_test/testfg1")
     66        # Second file should have an '_'
     67        p3 = Photo(title="test1")
     68        p3.save_image_file('testfg1', self.img_content)
     69        self.assert_(os.path.exists(p3.get_image_filename()))
     70        self.assertNotEqual(p2.image, p3.image)
     71        self.assertEqual(p3.image, "file_field_test/testfg1_")
     72       
     73    def testFileSaving(self):
     74        "Test we actually put the content into the file"
     75        p = Photo(title="test")
     76        p.save_image_file('tests0.jpg', self.img_content)
     77        self.assert_(os.path.exists(p.get_image_filename()))
     78        saved_img = open(p.get_image_filename(), 'rb').read()
     79        self.assertEqual(self.img_content, saved_img)
     80   
    3781    def tearDown(self):
    3882        """
    39         Make sure to delete the "uploaded" file to avoid clogging /tmp.
     83        Make sure to delete the "uploaded" files to avoid clogging /tmp.
    4084        """
    41         p = Photo.objects.get()
    42         os.unlink(p.get_image_filename())
    43  No newline at end of file
     85        shutil.rmtree(os.path.join(settings.MEDIA_ROOT, 'file_field_test'))
     86        settings.MEDIA_ROOT = self.old_media_root
  • tests/regressiontests/file_field/models.py

     
    1 import tempfile
    21from django.db import models
    32
    43class Photo(models.Model):
    54    title = models.CharField(max_length=30)
    6     image = models.FileField(upload_to=tempfile.gettempdir())
     5    image = models.FileField(upload_to='file_field_test')
    76   
    87    # Support code for the tests; this keeps track of how many times save() gets
    98    # called on each instance.
Back to Top