Django

Code

Show
Ignore:
Timestamp:
07/01/08 10:10:51 (4 months ago)
Author:
jacob
Message:

Fixed #2070: refactored Django's file upload capabilities.

A description of the new features can be found in the new upload handling documentation; the executive summary is that Django will now happily handle uploads of large files without issues.

This changes the representation of uploaded files from dictionaries to bona fide objects; see BackwardsIncompatibleChanges for details.

Files:

Legend:

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

    r7795 r7814  
    2020from django.utils.functional import curry 
    2121from django.utils.encoding import smart_str, force_unicode, smart_unicode 
     22from django.core.files.move import file_move_safe 
     23from django.core.files import locks 
    2224from django.conf import settings 
    2325 
     
    470472        return os.path.getsize(self._get_FIELD_filename(field)) 
    471473 
    472     def _save_FIELD_file(self, field, filename, raw_contents, save=True): 
     474    def _save_FIELD_file(self, field, filename, raw_field, save=True): 
    473475        directory = field.get_directory_name() 
    474476        try: # Create the date-based directory if it doesn't exist. 
     
    476478        except OSError: # Directory probably already exists. 
    477479            pass 
     480 
     481        # 
     482        # Check for old-style usage (files-as-dictionaries). Warn here first 
     483        # since there are multiple locations where we need to support both new 
     484        # and old usage. 
     485        # 
     486        if isinstance(raw_field, dict): 
     487            import warnings 
     488            warnings.warn( 
     489                message = "Representing uploaded files as dictionaries is"\ 
     490                          " deprected. Use django.core.files.SimpleUploadedFile"\ 
     491                          " instead.", 
     492                category = DeprecationWarning, 
     493                stacklevel = 2 
     494            ) 
     495            from django.core.files.uploadedfile import SimpleUploadedFile 
     496            raw_field = SimpleUploadedFile.from_dict(raw_field) 
     497 
     498        elif isinstance(raw_field, basestring): 
     499            import warnings 
     500            warnings.warn( 
     501                message = "Representing uploaded files as strings is "\ 
     502                          " deprecated. Use django.core.files.SimpleUploadedFile "\ 
     503                          " instead.", 
     504                category = DeprecationWarning, 
     505                stacklevel = 2 
     506            ) 
     507            from django.core.files.uploadedfile import SimpleUploadedFile 
     508            raw_field = SimpleUploadedFile(filename, raw_field) 
     509 
     510        if filename is None: 
     511            filename = raw_field.file_name 
     512 
    478513        filename = field.get_filename(filename) 
    479514 
     515        # 
    480516        # If the filename already exists, keep adding an underscore to the name of 
    481517        # the file until the filename doesn't exist. 
     518        # 
    482519        while os.path.exists(os.path.join(settings.MEDIA_ROOT, filename)): 
    483520            try: 
     
    487524            else: 
    488525                filename = filename[:dot_index] + '_' + filename[dot_index:] 
    489  
    490         # Write the file to disk. 
     526        # 
     527        # Save the file name on the object and write the file to disk 
     528        # 
     529 
    491530        setattr(self, field.attname, filename) 
    492531 
    493532        full_filename = self._get_FIELD_filename(field) 
    494         fp = open(full_filename, 'wb') 
    495         fp.write(raw_contents) 
    496         fp.close() 
     533 
     534        if hasattr(raw_field, 'temporary_file_path'): 
     535            # This file has a file path that we can move. 
     536            raw_field.close() 
     537            file_move_safe(raw_field.temporary_file_path(), full_filename) 
     538 
     539        else: 
     540            # This is a normal uploadedfile that we can stream. 
     541            fp = open(full_filename, 'wb') 
     542            locks.lock(fp, locks.LOCK_EX) 
     543            for chunk in raw_field.chunk(): 
     544                fp.write(chunk) 
     545            locks.unlock(fp) 
     546            fp.close() 
    497547 
    498548        # Save the width and/or height, if applicable.