Ticket #7614: third_patch.diff

File third_patch.diff, 10.8 KB (added by Michael Axiak, 16 years ago)

This patch has backwards "compatible" interfaces for people to use.

  • django/db/models/fields/__init__.py

     
    766766    def get_db_prep_save(self, value):
    767767        "Returns field's value prepared for saving into a database."
    768768        # Need to convert UploadedFile objects provided via a form to unicode for database insertion
    769         if value is None:
     769        if hasattr(value, 'file_name'):
     770            return value.file_name
     771        elif value is None:
    770772            return None
    771         return unicode(value)
     773        else:
     774            return unicode(value)
    772775
    773776    def get_manipulator_fields(self, opts, manipulator, change, name_prefix='', rel=False, follow=True):
    774777        field_list = Field.get_manipulator_fields(self, opts, manipulator, change, name_prefix, rel, follow)
     
    857860        return os.path.normpath(f)
    858861
    859862    def save_form_data(self, instance, data):
    860         from django.newforms.fields import UploadedFile
     863        from django.core.files.uploadedfile import UploadedFile
    861864        if data and isinstance(data, UploadedFile):
    862             getattr(instance, "save_%s_file" % self.name)(data.filename, data.data, save=False)
     865            getattr(instance, "save_%s_file" % self.name)(data.file_name, data, save=False)
    863866
    864867    def formfield(self, **kwargs):
    865868        defaults = {'form_class': forms.FileField}
  • django/core/files/uploadedfile.py

     
    33"""
    44
    55import os
     6import warnings
    67try:
    78    from cStringIO import StringIO
    89except ImportError:
     
    2122    DEFAULT_CHUNK_SIZE = 64 * 2**10
    2223
    2324    def __init__(self, file_name=None, content_type=None, file_size=None, charset=None):
    24         self.file_name = file_name
     25        self.name = file_name
    2526        self.file_size = file_size
    2627        self.content_type = content_type
    2728        self.charset = charset
    2829
    2930    def __repr__(self):
    30         return "<%s: %s (%s)>" % (self.__class__.__name__, self.file_name, self.content_type)
     31        return "<%s: %s (%s)>" % (self.__class__.__name__, self.name, self.content_type)
    3132
    32     def _set_file_name(self, name):
     33    def _set_name(self, name):
    3334        # Sanitize the file name so that it can't be dangerous.
    3435        if name is not None:
    3536            # Just use the basename of the file -- anything else is dangerous.
    3637            name = os.path.basename(name)
    37            
     38
    3839            # File names longer than 255 characters can cause problems on older OSes.
    3940            if len(name) > 255:
    4041                name, ext = os.path.splitext(name)
    4142                name = name[:255 - len(ext)] + ext
    42                
    43         self._file_name = name
    44        
     43
     44        self._name = name
     45
     46    def _get_name(self):
     47        return self._name
     48
     49    name = property(_get_name, _set_name)
     50
    4551    def _get_file_name(self):
    46         return self._file_name
    47        
    48     file_name = property(_get_file_name, _set_file_name)
     52        warnings.warn(
     53            message = "To access the filename, please use the .name attribute.",
     54            category = DeprecationWarning,
     55            stacklevel = 1,
     56        )
     57        return self.name
    4958
     59    def _set_file_name(self, name):
     60        warnings.warn(
     61            message = "To access the filename, please use the .name attribute.",
     62            category = DeprecationWarning,
     63            stacklevel = 1,
     64        )
     65        self.name = name
     66
     67    file_name = filename = property(_get_file_name, _set_file_name)
     68
     69    def _get_data(self):
     70        warnings.warn(
     71            message = "To access the data, please use the .read() or .chunk() UploadedFile interface.",
     72            category = DeprecationWarning,
     73            stacklevel = 1,
     74            )
     75        return self.read()
     76
     77    data = property(_get_data)
     78
    5079    def chunk(self, chunk_size=None):
    5180        """
    5281        Read the file and yield chucks of ``chunk_size`` bytes (defaults to
     
    76105            chunk_size = UploadedFile.DEFAULT_CHUNK_SIZE
    77106        return self.file_size < chunk_size
    78107
    79     # Abstract methods; subclasses *must* default read() and probably should
     108    # Abstract methods; subclasses *must* define read() and probably should
    80109    # define open/close.
    81110    def read(self, num_bytes=None):
    82111        raise NotImplementedError()
     
    96125            stacklevel = 2
    97126        )
    98127        backwards_translate = {
    99             'filename': 'file_name',
     128            'filename': 'name',
    100129            'content-type': 'content_type',
    101130            }
    102131
    103132        if key == 'content':
    104133            return self.read()
    105134        elif key == 'filename':
    106             return self.file_name
     135            return self.name
    107136        elif key == 'content-type':
    108137            return self.content_type
    109138        else:
     
    168197    """
    169198    def __init__(self, name, content, content_type='text/plain'):
    170199        self.file = StringIO(content or '')
    171         self.file_name = name
     200        self.name = name
    172201        self.field_name = None
    173202        self.file_size = len(content or '')
    174203        self.content_type = content_type
     
    188217                   file_dict.get('content-type', 'text/plain'))
    189218
    190219    from_dict = classmethod(from_dict)
     220
     221    def read(self):
     222        self.file.seek(0)
     223        return super(SimpleUploadedFile, self).read()
     224       
  • django/newforms/fields.py

     
    2727
    2828from util import ErrorList, ValidationError
    2929from widgets import TextInput, PasswordInput, HiddenInput, MultipleHiddenInput, FileInput, CheckboxInput, Select, NullBooleanSelect, SelectMultiple, DateTimeInput
     30from django.core.files.uploadedfile import SimpleUploadedFile as UploadedFile
    3031
    31 
    3232__all__ = (
    3333    'Field', 'CharField', 'IntegerField',
    3434    'DEFAULT_DATE_INPUT_FORMATS', 'DateField',
     
    419419    # It's OK if Django settings aren't configured.
    420420    URL_VALIDATOR_USER_AGENT = 'Django (http://www.djangoproject.com/)'
    421421
    422 class UploadedFile(StrAndUnicode):
    423     "A wrapper for files uploaded in a FileField"
    424     def __init__(self, filename, data):
    425         self.filename = filename
    426         self.data = data
    427422
    428     def __unicode__(self):
    429         """
    430         The unicode representation is the filename, so that the pre-database-insertion
    431         logic can use UploadedFile objects
    432         """
    433         return self.filename
    434 
    435423class FileField(Field):
    436424    widget = FileInput
    437425    default_error_messages = {
     
    460448                category = DeprecationWarning,
    461449                stacklevel = 2
    462450            )
     451            data = UploadedFile(data['filename'], data['content'])
    463452
    464453        try:
    465454            file_name = data.file_name
    466455            file_size = data.file_size
    467456        except AttributeError:
    468             try:
    469                 file_name = data.get('filename')
    470                 file_size = bool(data['content'])
    471             except (AttributeError, KeyError):
    472                 raise ValidationError(self.error_messages['invalid'])
     457            raise ValidationError(self.error_messages['invalid'])
    473458
    474459        if not file_name:
    475460            raise ValidationError(self.error_messages['invalid'])
    476461        if not file_size:
    477462            raise ValidationError(self.error_messages['empty'])
    478463
    479         return UploadedFile(file_name, data)
     464        return data
    480465
    481466class ImageField(FileField):
    482467    default_error_messages = {
  • tests/modeltests/model_forms/models.py

     
    803803>>> f.is_valid()
    804804True
    805805>>> type(f.cleaned_data['file'])
    806 <class 'django.newforms.fields.UploadedFile'>
     806<class 'django.core.files.uploadedfile.SimpleUploadedFile'>
    807807>>> instance = f.save()
    808808>>> instance.file
    809809u'...test1.txt'
     
    814814>>> f.is_valid()
    815815True
    816816>>> type(f.cleaned_data['file'])
    817 <class 'django.newforms.fields.UploadedFile'>
     817<class 'django.core.files.uploadedfile.SimpleUploadedFile'>
    818818>>> instance = f.save()
    819819>>> instance.file
    820820u'...test1.txt'
     
    906906>>> f.is_valid()
    907907True
    908908>>> type(f.cleaned_data['image'])
    909 <class 'django.newforms.fields.UploadedFile'>
     909<class 'django.core.files.uploadedfile.SimpleUploadedFile'>
    910910>>> instance = f.save()
    911911>>> instance.image
    912912u'...test.png'
     
    918918>>> f.is_valid()
    919919True
    920920>>> type(f.cleaned_data['image'])
    921 <class 'django.newforms.fields.UploadedFile'>
     921<class 'django.core.files.uploadedfile.SimpleUploadedFile'>
    922922>>> instance = f.save()
    923923>>> instance.image
    924924u'...test.png'
  • tests/regressiontests/forms/fields.py

     
    800800ValidationError: [u'The submitted file is empty.']
    801801
    802802>>> type(f.clean(SimpleUploadedFile('name', 'Some File Content')))
    803 <class 'django.newforms.fields.UploadedFile'>
     803<class 'django.core.files.uploadedfile.SimpleUploadedFile'>
    804804
    805805>>> type(f.clean(SimpleUploadedFile('name', 'Some File Content'), 'files/test4.pdf'))
    806 <class 'django.newforms.fields.UploadedFile'>
     806<class 'django.core.files.uploadedfile.SimpleUploadedFile'>
    807807
    808808# URLField ##################################################################
    809809
  • docs/newforms.txt

     
    13311331    * Validates that non-empty file data has been bound to the form.
    13321332    * Error message keys: ``required``, ``invalid``, ``missing``, ``empty``
    13331333
    1334 An ``UploadedFile`` object has two attributes:
     1334To learn more about the ``UploadedFile`` object, see the `file uploads documentation`_.
    13351335
    1336     ======================  ====================================================
    1337     Attribute               Description
    1338     ======================  ====================================================
    1339     ``filename``            The name of the file, provided by the uploading
    1340                             client.
    1341                            
    1342     ``content``             The array of bytes comprising the file content.
    1343     ======================  ====================================================
    1344 
    1345 The string representation of an ``UploadedFile`` is the same as the filename
    1346 attribute.
    1347 
    13481336When you use a ``FileField`` on a form, you must also remember to
    13491337`bind the file data to the form`_.
    13501338
     1339.. _file uploads documentation: ../upload_handling/
    13511340.. _`bind the file data to the form`: `Binding uploaded files to a form`_
    13521341
    13531342``FilePathField``
Back to Top