Ticket #2070: 2070_revision7599.diff

File 2070_revision7599.diff, 45.6 KB (added by Leah Culver, 16 years ago)

Updated patch to r7599

  • django/test/client.py

     
    1919BOUNDARY = 'BoUnDaRyStRiNg'
    2020MULTIPART_CONTENT = 'multipart/form-data; boundary=%s' % BOUNDARY
    2121
     22class FakePayload(object):
     23    """
     24    A wrapper around StringIO that restricts what can be read,
     25    since data from the network can't be seeked and cannot
     26    be read outside of its content length (or else we hang).
     27    """
     28    def __init__(self, content):
     29        self.__content = StringIO(content)
     30        self.__len = len(content)
     31
     32    def read(self, num_bytes=None):
     33        if num_bytes is None:
     34            num_bytes = self.__len or 1
     35        assert self.__len >= num_bytes, "Cannot read more than the available bytes from the HTTP incoming data."
     36        content = self.__content.read(num_bytes)
     37        self.__len -= num_bytes
     38        return content
     39
    2240class ClientHandler(BaseHandler):
    2341    """
    2442    A HTTP Handler that can be used for testing purposes.
     
    236254            'CONTENT_TYPE':   content_type,
    237255            'PATH_INFO':      urllib.unquote(path),
    238256            'REQUEST_METHOD': 'POST',
    239             'wsgi.input':     StringIO(post_data),
     257            'wsgi.input':     FakePayload(post_data),
    240258        }
    241259        r.update(extra)
    242260
     
    280298        """
    281299        session = __import__(settings.SESSION_ENGINE, {}, {}, ['']).SessionStore()
    282300        session.delete(session_key=self.cookies[settings.SESSION_COOKIE_NAME].value)
    283         self.cookies = SimpleCookie()
     301        self.cookies = SimpleCookie()
     302 No newline at end of file
  • django/http/__init__.py

     
    99except ImportError:
    1010    from cgi import parse_qsl
    1111
    12 from django.utils.datastructures import MultiValueDict, FileDict
     12from django.utils.datastructures import MultiValueDict, ImmutableList
    1313from django.utils.encoding import smart_str, iri_to_uri, force_unicode
    14 
     14from django.http.multipartparser import MultiPartParser
    1515from utils import *
    1616
    1717RESERVED_CHARS="!*'();:@&=+$,/?%#[]"
     
    2525
    2626    # The encoding used in GET/POST dicts. None means use default setting.
    2727    _encoding = None
     28    _upload_handlers = ()
    2829
    2930    def __init__(self):
    3031        self.GET, self.POST, self.COOKIES, self.META, self.FILES = {}, {}, {}, {}, {}
     
    102103
    103104    encoding = property(_get_encoding, _set_encoding)
    104105
    105 def parse_file_upload(header_dict, post_data):
    106     """Returns a tuple of (POST QueryDict, FILES MultiValueDict)."""
    107     import email, email.Message
    108     from cgi import parse_header
    109     raw_message = '\r\n'.join(['%s:%s' % pair for pair in header_dict.items()])
    110     raw_message += '\r\n\r\n' + post_data
    111     msg = email.message_from_string(raw_message)
    112     POST = QueryDict('', mutable=True)
    113     FILES = MultiValueDict()
    114     for submessage in msg.get_payload():
    115         if submessage and isinstance(submessage, email.Message.Message):
    116             name_dict = parse_header(submessage['Content-Disposition'])[1]
    117             # name_dict is something like {'name': 'file', 'filename': 'test.txt'} for file uploads
    118             # or {'name': 'blah'} for POST fields
    119             # We assume all uploaded files have a 'filename' set.
    120             if 'filename' in name_dict:
    121                 assert type([]) != type(submessage.get_payload()), "Nested MIME messages are not supported"
    122                 if not name_dict['filename'].strip():
    123                     continue
    124                 # IE submits the full path, so trim everything but the basename.
    125                 # (We can't use os.path.basename because that uses the server's
    126                 # directory separator, which may not be the same as the
    127                 # client's one.)
    128                 filename = name_dict['filename'][name_dict['filename'].rfind("\\")+1:]
    129                 FILES.appendlist(name_dict['name'], FileDict({
    130                     'filename': filename,
    131                     'content-type': 'Content-Type' in submessage and submessage['Content-Type'] or None,
    132                     'content': submessage.get_payload(),
    133                 }))
    134             else:
    135                 POST.appendlist(name_dict['name'], submessage.get_payload())
    136     return POST, FILES
     106    def _initialize_handlers(self):
     107        from django.conf import settings
     108        from django.core.files.uploadhandler import load_handler
     109        handlers = []
     110        # We go through each handler in the settings variable
     111        # and instantiate the handler by calling HandlerClass(request).
     112        for handler in settings.FILE_UPLOAD_HANDLERS:
     113            handlers.append(load_handler(handler, self))
     114        self._upload_handlers = handlers
    137115
     116    def _set_upload_handlers(self, upload_handlers):
     117        """
     118        Set the upload handler to the new handler given in the parameter.
     119        """
     120        if hasattr(self, '_files'):
     121            raise AttributeError("You cannot set the upload handlers after the upload has been processed.")
     122        self._upload_handlers = upload_handlers
    138123
     124    def _get_upload_handlers(self):
     125        if not self._upload_handlers:
     126            # If thre are no upload handlers defined, initialize them from settings.
     127            self._initialize_handlers()
     128        return self._upload_handlers
     129
     130    upload_handlers = property(_get_upload_handlers, _set_upload_handlers)
     131
     132    def parse_file_upload(self, META, post_data):
     133        """Returns a tuple of (POST QueryDict, FILES MultiValueDict)."""
     134        self.upload_handlers = ImmutableList(self.upload_handlers,
     135                                             warning="You cannot alter the upload handlers after the upload has been processed.")
     136        parser = MultiPartParser(META, post_data, self.upload_handlers,
     137                                 self.encoding)
     138        return parser.parse()
     139
    139140class QueryDict(MultiValueDict):
    140141    """
    141142    A specialized MultiValueDict that takes a query string when initialized.
  • django/oldforms/__init__.py

     
    680680        self.field_name, self.is_required = field_name, is_required
    681681        self.validator_list = [self.isNonEmptyFile] + validator_list
    682682
    683     def isNonEmptyFile(self, field_data, all_data):
     683    def isNonEmptyFile(self, new_data, all_data):
     684        if hasattr(new_data, 'upload_errors'):
     685            upload_errors = new_data.upload_errors()
     686            if upload_errors:
     687                raise validators.CriticalValidationError, upload_errors
    684688        try:
    685             content = field_data['content']
    686         except TypeError:
    687             raise validators.CriticalValidationError, ugettext("No file was submitted. Check the encoding type on the form.")
    688         if not content:
     689            file_size = new_data.file_size
     690        except AttributeError:
     691            file_size = len(new_data['content'])
     692        if not file_size:
    689693            raise validators.CriticalValidationError, ugettext("The submitted file is empty.")
    690694
    691695    def render(self, data):
    692696        return mark_safe(u'<input type="file" id="%s" class="v%s" name="%s" />' % \
    693697            (self.get_id(), self.__class__.__name__, self.field_name))
    694698
     699    def prepare(self, new_data):
     700        if hasattr(new_data, 'upload_errors'):
     701            upload_errors = new_data.upload_errors()
     702            new_data[self.field_name] = { '_file_upload_error': upload_errors }
     703
    695704    def html2python(data):
    696705        if data is None:
    697706            raise EmptyValue
  • django/db/models/base.py

     
    1919from django.utils.datastructures import SortedDict
    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
    2223from django.conf import settings
    2324
    2425try:
     
    447448    def _get_FIELD_size(self, field):
    448449        return os.path.getsize(self._get_FIELD_filename(field))
    449450
    450     def _save_FIELD_file(self, field, filename, raw_contents, save=True):
     451    def _save_FIELD_file(self, field, filename, raw_field, save=True):
    451452        directory = field.get_directory_name()
    452453        try: # Create the date-based directory if it doesn't exist.
    453454            os.makedirs(os.path.join(settings.MEDIA_ROOT, directory))
    454455        except OSError: # Directory probably already exists.
    455456            pass
     457
     458        # Put the deprecation warning first since there are multiple
     459        # locations where we use the new and old interface.
     460        if isinstance(raw_field, dict):
     461            import warnings
     462            from django.core.files.uploadedfile import SimpleUploadedFile
     463            raw_field = SimpleUploadedFile.from_dict(raw_field)
     464            warnings.warn("The dictionary usage for files is deprecated. Use the new object interface instead.", DeprecationWarning)
     465        elif isinstance(raw_field, basestring):
     466            import warnings
     467            from django.core.files.uploadedfile import SimpleUploadedFile
     468            raw_field = SimpleUploadedFile(filename, raw_field)
     469            warnings.warn("The string interface for save_FIELD_file is deprecated.", DeprecationWarning)
     470
     471        if filename is None:
     472            filename = raw_field.file_name
     473
    456474        filename = field.get_filename(filename)
    457475
    458476        # If the filename already exists, keep adding an underscore to the name of
     
    469487        setattr(self, field.attname, filename)
    470488
    471489        full_filename = self._get_FIELD_filename(field)
    472         fp = open(full_filename, 'wb')
    473         fp.write(raw_contents)
    474         fp.close()
     490        if hasattr(raw_field, 'temporary_file_path'):
     491            # This file has a file path that we can move.
     492            raw_field.close()
     493            file_move_safe(raw_field.temporary_file_path(), full_filename)
     494        else:
     495            from django.core.files import locks
     496            fp = open(full_filename, 'wb')
     497            # exclusive lock
     498            locks.lock(fp, locks.LOCK_EX)
     499            # This is a normal uploadedfile that we can stream.
     500            for chunk in raw_field.chunk(65535):
     501                fp.write(chunk)
     502            locks.unlock(fp)
     503            fp.close()
    475504
    476505        # Save the width and/or height, if applicable.
    477506        if isinstance(field, ImageField) and (field.width_field or field.height_field):
  • django/db/models/fields/__init__.py

     
    806806        setattr(cls, 'get_%s_filename' % self.name, curry(cls._get_FIELD_filename, field=self))
    807807        setattr(cls, 'get_%s_url' % self.name, curry(cls._get_FIELD_url, field=self))
    808808        setattr(cls, 'get_%s_size' % self.name, curry(cls._get_FIELD_size, field=self))
    809         setattr(cls, 'save_%s_file' % self.name, lambda instance, filename, raw_contents, save=True: instance._save_FIELD_file(self, filename, raw_contents, save))
     809        setattr(cls, 'save_%s_file' % self.name, lambda instance, filename, raw_field, save=True: instance._save_FIELD_file(self, filename, raw_field, save))
    810810        dispatcher.connect(self.delete_file, signal=signals.post_delete, sender=cls)
    811811
    812812    def delete_file(self, instance):
     
    829829        if new_data.get(upload_field_name, False):
    830830            func = getattr(new_object, 'save_%s_file' % self.name)
    831831            if rel:
    832                 func(new_data[upload_field_name][0]["filename"], new_data[upload_field_name][0]["content"], save)
     832                file = new_data[upload_field_name][0]
    833833            else:
    834                 func(new_data[upload_field_name]["filename"], new_data[upload_field_name]["content"], save)
     834                file = new_data[upload_field_name]
    835835
     836            try:
     837                file_name = file.file_name
     838            except AttributeError:
     839                file_name = file['filename']
     840            func(file_name, file, save)
     841
    836842    def get_directory_name(self):
    837843        return os.path.normpath(force_unicode(datetime.datetime.now().strftime(smart_str(self.upload_to))))
    838844
     
    844850    def save_form_data(self, instance, data):
    845851        from django.newforms.fields import UploadedFile
    846852        if data and isinstance(data, UploadedFile):
    847             getattr(instance, "save_%s_file" % self.name)(data.filename, data.content, save=False)
     853            getattr(instance, "save_%s_file" % self.name)(data.filename, data.data, save=False)
    848854
    849855    def formfield(self, **kwargs):
    850856        defaults = {'form_class': forms.FileField}
  • django/conf/global_settings.py

     
    228228# Example: "http://media.lawrence.com"
    229229MEDIA_URL = ''
    230230
     231# A tuple that enumerates the upload handlers
     232# in order.
     233FILE_UPLOAD_HANDLERS = (
     234    'django.core.files.uploadhandler.MemoryFileUploadHandler',
     235    'django.core.files.uploadhandler.TemporaryFileUploadHandler',
     236)
     237
     238# Number of bytes the length of the request can be before it is
     239# streamed to the file system instead of parsed entirely in memory.
     240FILE_UPLOAD_MAX_MEMORY_SIZE = 2621440
     241
     242# Directory to upload streamed files temporarily.
     243# A value of `None` means that it will use the default temporary
     244# directory for the server's operating system.
     245FILE_UPLOAD_TEMP_DIR = None
     246
    231247# Default formatting for date objects. See all available format strings here:
    232248# http://www.djangoproject.com/documentation/templates/#now
    233249DATE_FORMAT = 'N j, Y'
  • django/core/handlers/wsgi.py

     
    112112        # Populates self._post and self._files
    113113        if self.method == 'POST':
    114114            if self.environ.get('CONTENT_TYPE', '').startswith('multipart'):
    115                 header_dict = dict([(k, v) for k, v in self.environ.items() if k.startswith('HTTP_')])
    116                 header_dict['Content-Type'] = self.environ.get('CONTENT_TYPE', '')
    117                 self._post, self._files = http.parse_file_upload(header_dict, self.raw_post_data)
     115                self._raw_post_data = ''
     116                self._post, self._files = self.parse_file_upload(self.META, self.environ['wsgi.input'])
    118117            else:
    119118                self._post, self._files = http.QueryDict(self.raw_post_data, encoding=self._encoding), datastructures.MultiValueDict()
    120119        else:
  • django/core/handlers/modpython.py

     
    5353    def _load_post_and_files(self):
    5454        "Populates self._post and self._files"
    5555        if 'content-type' in self._req.headers_in and self._req.headers_in['content-type'].startswith('multipart'):
    56             self._post, self._files = http.parse_file_upload(self._req.headers_in, self.raw_post_data)
     56            self._raw_post_data = ''
     57            self._post, self._files = self.parse_file_upload(self.META, self._req)
    5758        else:
    5859            self._post, self._files = http.QueryDict(self.raw_post_data, encoding=self._encoding), datastructures.MultiValueDict()
    5960
  • django/newforms/fields.py

     
    44
    55import copy
    66import datetime
     7import warnings
    78import os
    89import re
    910import time
     
    416417
    417418class UploadedFile(StrAndUnicode):
    418419    "A wrapper for files uploaded in a FileField"
    419     def __init__(self, filename, content):
     420    def __init__(self, filename, data):
    420421        self.filename = filename
    421         self.content = content
     422        self.data = data
    422423
    423424    def __unicode__(self):
    424425        """
     
    444445            return None
    445446        elif not data and initial:
    446447            return initial
     448
     449        if isinstance(data, dict):
     450            # We warn once, then support both ways below.
     451            warnings.warn("The dictionary usage for files is deprecated. Use the new object interface instead.", DeprecationWarning)
     452
    447453        try:
    448             f = UploadedFile(data['filename'], data['content'])
    449         except TypeError:
     454            file_name = data.file_name
     455            file_size = data.file_size
     456        except AttributeError:
     457            try:
     458                file_name = data.get('filename')
     459                file_size = bool(data['content'])
     460            except (AttributeError, KeyError):
     461                raise ValidationError(self.error_messages['invalid'])
     462
     463        if not file_name:
    450464            raise ValidationError(self.error_messages['invalid'])
    451         except KeyError:
    452             raise ValidationError(self.error_messages['missing'])
    453         if not f.content:
     465        if not file_size:
    454466            raise ValidationError(self.error_messages['empty'])
    455         return f
    456467
     468        return UploadedFile(file_name, data)
     469
    457470class ImageField(FileField):
    458471    default_error_messages = {
    459472        'invalid_image': _(u"Upload a valid image. The file you uploaded was either not an image or a corrupted image."),
     
    470483        elif not data and initial:
    471484            return initial
    472485        from PIL import Image
    473         from cStringIO import StringIO
     486
     487        # We need to get the file, it either has a path
     488        # or we have to read it all into memory...
     489        if hasattr(data, 'temporary_file_path'):
     490            file = data.temporary_file_path()
     491        else:
     492            try:
     493                from cStringIO import StringIO
     494            except ImportError:
     495                from StringIO import StringIO
     496            if hasattr(data, 'read'):
     497                file = StringIO(data.read())
     498            else:
     499                file = StringIO(data['content'])
     500
    474501        try:
    475502            # load() is the only method that can spot a truncated JPEG,
    476503            #  but it cannot be called sanely after verify()
    477             trial_image = Image.open(StringIO(f.content))
     504            trial_image = Image.open(file)
    478505            trial_image.load()
     506
     507            # Since we're about to use the file again, we have to
     508            # reset the cursor of the file object if it has a cursor
     509            # to reset.
     510            if hasattr(file, 'reset'):
     511                file.reset()
     512
    479513            # verify() is the only method that can spot a corrupt PNG,
    480514            #  but it must be called immediately after the constructor
    481             trial_image = Image.open(StringIO(f.content))
     515            trial_image = Image.open(file)
    482516            trial_image.verify()
    483517        except Exception: # Python Imaging Library doesn't recognize it as an image
    484518            raise ValidationError(self.error_messages['invalid_image'])
  • django/utils/datastructures.py

     
    332332            except TypeError: # Special-case if current isn't a dict.
    333333                current = {bits[-1]: v}
    334334
    335 class FileDict(dict):
     335class ImmutableList(tuple):
    336336    """
    337     A dictionary used to hold uploaded file contents. The only special feature
    338     here is that repr() of this object won't dump the entire contents of the
    339     file to the output. A handy safeguard for a large file upload.
     337    A tuple-like object that raises useful
     338    errors when it is asked to mutate.
     339    Example::
     340        a = ImmutableList(range(5), warning=AttributeError("You cannot mutate this."))
     341        a[3] = '4'
     342        (Raises the AttributeError)
    340343    """
    341     def __repr__(self):
    342         if 'content' in self:
    343             d = dict(self, content='<omitted>')
    344             return dict.__repr__(d)
    345         return dict.__repr__(self)
     344
     345    def __new__(cls, *args, **kwargs):
     346        if 'warning' in kwargs:
     347            warning = kwargs['warning']
     348            del kwargs['warning']
     349        else:
     350            warning = 'ImmutableList object is immutable.'
     351        self = tuple.__new__(cls, *args, **kwargs)
     352        self.warning = warning
     353        return self
     354
     355    def complain(self, *wargs, **kwargs):
     356        if isinstance(self.warning, Exception):
     357            raise self.warning
     358        else:
     359            raise AttributeError, self.warning
     360
     361    # All list mutation functions become complain.
     362    __delitem__ = __delslice__ = __iadd__ = __imul__ = complain
     363    __setitem__ = __setslice__ = complain
     364    append = extend = insert = pop = remove = complain
     365    sort = reverse = complain
  • django/utils/text.py

     
    33from django.utils.encoding import force_unicode
    44from django.utils.functional import allow_lazy
    55from django.utils.translation import ugettext_lazy
     6from htmlentitydefs import name2codepoint
    67
    78# Capitalizes the first letter of a string.
    89capfirst = lambda x: x and force_unicode(x)[0].upper() + force_unicode(x)[1:]
     
    222223            yield bit
    223224smart_split = allow_lazy(smart_split, unicode)
    224225
     226def _replace_entity(match):
     227     text = match.group(1)
     228     if text[0] == u'#':
     229         text = text[1:]
     230         try:
     231             if text[0] in u'xX':
     232                 c = int(text[1:], 16)
     233             else:
     234                 c = int(text)
     235             return unichr(c)
     236         except ValueError:
     237             return match.group(0)
     238     else:
     239         try:
     240             return unichr(name2codepoint[text])
     241         except (ValueError, KeyError):
     242             return match.group(0)
     243
     244_entity_re = re.compile(r"&(#?[xX]?(?:[0-9a-fA-F]+|\w{1,8}));")
     245
     246def unescape_entities(text):
     247     return _entity_re.sub(_replace_entity, text)
     248unescape_entities = allow_lazy(unescape_entities, unicode)
  • tests/modeltests/model_forms/models.py

     
    6767
    6868class ImageFile(models.Model):
    6969    description = models.CharField(max_length=20)
    70     image = models.FileField(upload_to=tempfile.gettempdir())
     70    try:
     71        # If PIL is available, try testing PIL.
     72        # Otherwise, it's equivalent to TextFile above.
     73        import Image
     74        image = models.ImageField(upload_to=tempfile.gettempdir())
     75    except ImportError:
     76        image = models.FileField(upload_to=tempfile.gettempdir())
    7177
    7278    def __unicode__(self):
    7379        return self.description
     
    7581__test__ = {'API_TESTS': """
    7682>>> from django import newforms as forms
    7783>>> from django.newforms.models import ModelForm
     84>>> from django.core.files.uploadedfile import SimpleUploadedFile
     85>>> from warnings import filterwarnings
     86>>> filterwarnings("ignore")
    7887
    7988The bare bones, absolutely nothing custom, basic case.
    8089
     
    792801
    793802# Upload a file and ensure it all works as expected.
    794803
     804>>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': SimpleUploadedFile('test1.txt', 'hello world')})
     805>>> f.is_valid()
     806True
     807>>> type(f.cleaned_data['file'])
     808<class 'django.newforms.fields.UploadedFile'>
     809>>> instance = f.save()
     810>>> instance.file
     811u'...test1.txt'
     812
     813>>> os.unlink(instance.get_file_filename())
     814
    795815>>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': {'filename': 'test1.txt', 'content': 'hello world'}})
    796816>>> f.is_valid()
    797817True
     
    814834u'...test1.txt'
    815835
    816836# Delete the current file since this is not done by Django.
    817 
    818837>>> os.unlink(instance.get_file_filename())
    819838
    820839# Override the file by uploading a new one.
    821840
    822 >>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': {'filename': 'test2.txt', 'content': 'hello world'}}, instance=instance)
     841>>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': SimpleUploadedFile('test2.txt', 'hello world')}, instance=instance)
    823842>>> f.is_valid()
    824843True
    825844>>> instance = f.save()
    826845>>> instance.file
    827846u'...test2.txt'
    828847
     848# Delete the current file since this is not done by Django.
     849>>> os.unlink(instance.get_file_filename())
     850
     851>>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': {'filename': 'test2.txt', 'content': 'hello world'}})
     852>>> f.is_valid()
     853True
     854>>> instance = f.save()
     855>>> instance.file
     856u'...test2.txt'
     857
     858# Delete the current file since this is not done by Django.
     859>>> os.unlink(instance.get_file_filename())
     860
    829861>>> instance.delete()
    830862
    831863# Test the non-required FileField
     
    838870>>> instance.file
    839871''
    840872
    841 >>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': {'filename': 'test3.txt', 'content': 'hello world'}}, instance=instance)
     873>>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': SimpleUploadedFile('test3.txt', 'hello world')}, instance=instance)
    842874>>> f.is_valid()
    843875True
    844876>>> instance = f.save()
    845877>>> instance.file
    846878u'...test3.txt'
     879
     880# Delete the current file since this is not done by Django.
     881>>> os.unlink(instance.get_file_filename())
    847882>>> instance.delete()
    848883
     884>>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': {'filename': 'test3.txt', 'content': 'hello world'}})
     885>>> f.is_valid()
     886True
     887>>> instance = f.save()
     888>>> instance.file
     889u'...test3.txt'
     890
     891# Delete the current file since this is not done by Django.
     892>>> os.unlink(instance.get_file_filename())
     893>>> instance.delete()
     894
    849895# ImageField ###################################################################
    850896
    851897# ImageField and FileField are nearly identical, but they differ slighty when
     
    858904
    859905>>> image_data = open(os.path.join(os.path.dirname(__file__), "test.png")).read()
    860906
     907>>> f = ImageFileForm(data={'description': u'An image'}, files={'image': SimpleUploadedFile('test.png', image_data)})
     908>>> f.is_valid()
     909True
     910>>> type(f.cleaned_data['image'])
     911<class 'django.newforms.fields.UploadedFile'>
     912>>> instance = f.save()
     913>>> instance.image
     914u'...test.png'
     915
     916# Delete the current file since this is not done by Django.
     917>>> os.unlink(instance.get_image_filename())
     918
    861919>>> f = ImageFileForm(data={'description': u'An image'}, files={'image': {'filename': 'test.png', 'content': image_data}})
    862920>>> f.is_valid()
    863921True
     
    885943
    886944# Override the file by uploading a new one.
    887945
    888 >>> f = ImageFileForm(data={'description': u'Changed it'}, files={'image': {'filename': 'test2.png', 'content': image_data}}, instance=instance)
     946>>> f = ImageFileForm(data={'description': u'Changed it'}, files={'image': SimpleUploadedFile('test2.png', image_data)}, instance=instance)
    889947>>> f.is_valid()
    890948True
    891949>>> instance = f.save()
    892950>>> instance.image
    893951u'...test2.png'
    894952
     953# Delete the current file since this is not done by Django.
     954>>> os.unlink(instance.get_image_filename())
    895955>>> instance.delete()
    896956
     957>>> f = ImageFileForm(data={'description': u'Changed it'}, files={'image': {'filename': 'test2.png', 'content': image_data}})
     958>>> f.is_valid()
     959True
     960>>> instance = f.save()
     961>>> instance.image
     962u'...test2.png'
     963
     964# Delete the current file since this is not done by Django.
     965>>> os.unlink(instance.get_image_filename())
     966>>> instance.delete()
     967
    897968# Test the non-required ImageField
    898969
    899970>>> f = ImageFileForm(data={'description': u'Test'})
     
    904975>>> instance.image
    905976''
    906977
    907 >>> f = ImageFileForm(data={'description': u'And a final one'}, files={'image': {'filename': 'test3.png', 'content': image_data}}, instance=instance)
     978>>> f = ImageFileForm(data={'description': u'And a final one'}, files={'image': SimpleUploadedFile('test3.png', image_data)}, instance=instance)
    908979>>> f.is_valid()
    909980True
    910981>>> instance = f.save()
    911982>>> instance.image
    912983u'...test3.png'
     984
     985# Delete the current file since this is not done by Django.
     986>>> os.unlink(instance.get_image_filename())
    913987>>> instance.delete()
    914988
     989>>> f = ImageFileForm(data={'description': u'And a final one'}, files={'image': {'filename': 'test3.png', 'content': image_data}})
     990>>> f.is_valid()
     991True
     992>>> instance = f.save()
     993>>> instance.image
     994u'...test3.png'
     995>>> instance.delete()
     996
    915997"""}
  • tests/regressiontests/bug639/tests.py

     
    99from regressiontests.bug639.models import Photo
    1010from django.http import QueryDict
    1111from django.utils.datastructures import MultiValueDict
     12from django.core.files.uploadedfile import SimpleUploadedFile
    1213
    1314class Bug639Test(unittest.TestCase):
    1415       
     
    2122       
    2223        # Fake a request query dict with the file
    2324        qd = QueryDict("title=Testing&image=", mutable=True)
    24         qd["image_file"] = {
    25             "filename" : "test.jpg",
    26             "content-type" : "image/jpeg",
    27             "content" : img
    28         }
    29        
     25        qd["image_file"] = SimpleUploadedFile('test.jpg', img, 'image/jpeg')
     26
    3027        manip = Photo.AddManipulator()
    3128        manip.do_html2python(qd)
    3229        p = manip.save(qd)
     
    3936        Make sure to delete the "uploaded" file to avoid clogging /tmp.
    4037        """
    4138        p = Photo.objects.get()
    42         os.unlink(p.get_image_filename())
    43  No newline at end of file
     39        os.unlink(p.get_image_filename())
  • tests/regressiontests/forms/error_messages.py

     
    11# -*- coding: utf-8 -*-
    22tests = r"""
    33>>> from django.newforms import *
     4>>> from django.core.files.uploadedfile import SimpleUploadedFile
    45
    56# CharField ###################################################################
    67
     
    214215Traceback (most recent call last):
    215216...
    216217ValidationError: [u'INVALID']
    217 >>> f.clean({})
     218>>> f.clean(SimpleUploadedFile('name', None))
    218219Traceback (most recent call last):
    219220...
    220 ValidationError: [u'MISSING']
    221 >>> f.clean({'filename': 'name', 'content':''})
     221ValidationError: [u'EMPTY FILE']
     222>>> f.clean(SimpleUploadedFile('name', ''))
    222223Traceback (most recent call last):
    223224...
    224225ValidationError: [u'EMPTY FILE']
  • tests/regressiontests/forms/tests.py

     
    2626from regressions import tests as regression_tests
    2727from util import tests as util_tests
    2828from widgets import tests as widgets_tests
     29from warnings import filterwarnings
     30filterwarnings("ignore")
    2931
    3032__test__ = {
    3133    'extra_tests': extra_tests,
  • tests/regressiontests/forms/fields.py

     
    22tests = r"""
    33>>> from django.newforms import *
    44>>> from django.newforms.widgets import RadioFieldRenderer
     5>>> from django.core.files.uploadedfile import SimpleUploadedFile
    56>>> import datetime
    67>>> import time
    78>>> import re
     
    773774>>> f.clean({})
    774775Traceback (most recent call last):
    775776...
    776 ValidationError: [u'No file was submitted.']
     777ValidationError: [u'No file was submitted. Check the encoding type on the form.']
    777778
    778779>>> f.clean({}, '')
    779780Traceback (most recent call last):
    780781...
    781 ValidationError: [u'No file was submitted.']
     782ValidationError: [u'No file was submitted. Check the encoding type on the form.']
    782783
    783784>>> f.clean({}, 'files/test3.pdf')
    784785'files/test3.pdf'
     
    788789...
    789790ValidationError: [u'No file was submitted. Check the encoding type on the form.']
    790791
    791 >>> f.clean({'filename': 'name', 'content': None})
     792>>> f.clean(SimpleUploadedFile('name', None))
    792793Traceback (most recent call last):
    793794...
    794795ValidationError: [u'The submitted file is empty.']
    795796
    796 >>> f.clean({'filename': 'name', 'content': ''})
     797>>> f.clean(SimpleUploadedFile('name', ''))
    797798Traceback (most recent call last):
    798799...
    799800ValidationError: [u'The submitted file is empty.']
    800801
    801 >>> type(f.clean({'filename': 'name', 'content': 'Some File Content'}))
     802>>> type(f.clean(SimpleUploadedFile('name', 'Some File Content')))
    802803<class 'django.newforms.fields.UploadedFile'>
    803804
    804 >>> type(f.clean({'filename': 'name', 'content': 'Some File Content'}, 'files/test4.pdf'))
     805>>> type(f.clean(SimpleUploadedFile('name', 'Some File Content'), 'files/test4.pdf'))
    805806<class 'django.newforms.fields.UploadedFile'>
    806807
    807808# URLField ##################################################################
  • tests/regressiontests/forms/forms.py

     
    11# -*- coding: utf-8 -*-
    22tests = r"""
    33>>> from django.newforms import *
     4>>> from django.core.files.uploadedfile import SimpleUploadedFile
    45>>> import datetime
    56>>> import time
    67>>> import re
     
    14651466>>> print f
    14661467<tr><th>File1:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="file" name="file1" /></td></tr>
    14671468
    1468 >>> f = FileForm(data={}, files={'file1': {'filename': 'name', 'content':''}}, auto_id=False)
     1469>>> f = FileForm(data={}, files={'file1': SimpleUploadedFile('name', '')}, auto_id=False)
    14691470>>> print f
    14701471<tr><th>File1:</th><td><ul class="errorlist"><li>The submitted file is empty.</li></ul><input type="file" name="file1" /></td></tr>
    14711472
     
    14731474>>> print f
    14741475<tr><th>File1:</th><td><ul class="errorlist"><li>No file was submitted. Check the encoding type on the form.</li></ul><input type="file" name="file1" /></td></tr>
    14751476
    1476 >>> f = FileForm(data={}, files={'file1': {'filename': 'name', 'content':'some content'}}, auto_id=False)
     1477>>> f = FileForm(data={}, files={'file1': SimpleUploadedFile('name', 'some content')}, auto_id=False)
    14771478>>> print f
    14781479<tr><th>File1:</th><td><input type="file" name="file1" /></td></tr>
    14791480>>> f.is_valid()
  • tests/regressiontests/test_client_regress/views.py

     
    11import os
     2import sha
    23
    34from django.contrib.auth.decorators import login_required
    45from django.http import HttpResponse, HttpResponseRedirect, HttpResponseServerError
     
    1314    Check that a file upload can be updated into the POST dictionary without
    1415    going pear-shaped.
    1516    """
     17    from django.core.files.uploadedfile import UploadedFile
    1618    form_data = request.POST.copy()
    1719    form_data.update(request.FILES)
    18     if isinstance(form_data['file_field'], dict) and isinstance(form_data['name'], unicode):
     20    if isinstance(form_data.get('file_field'), UploadedFile) and isinstance(form_data['name'], unicode):
    1921        # If a file is posted, the dummy client should only post the file name,
    2022        # not the full path.
    2123        if os.path.dirname(form_data['file_field']['filename']) != '':
     
    2426    else:
    2527        return HttpResponseServerError()
    2628
     29def file_upload_view_verify(request):
     30    """
     31    Use the sha digest hash to verify the uploaded contents.
     32    """
     33    from django.core.files.uploadedfile import UploadedFile
     34    form_data = request.POST.copy()
     35    form_data.update(request.FILES)
     36
     37    # Check to see if unicode names worked out.
     38    if not request.FILES['file_unicode'].file_name.endswith(u'test_\u4e2d\u6587_Orl\xe9ans.jpg'):
     39        return HttpResponseServerError()
     40
     41    for key, value in form_data.items():
     42        if key.endswith('_hash'):
     43            continue
     44        if key + '_hash' not in form_data:
     45            continue
     46        submitted_hash = form_data[key + '_hash']
     47        if isinstance(value, UploadedFile):
     48            new_hash = sha.new(value.read()).hexdigest()
     49        else:
     50            new_hash = sha.new(value).hexdigest()
     51        if new_hash != submitted_hash:
     52            return HttpResponseServerError()
     53
     54    return HttpResponse('')
     55
    2756def staff_only_view(request):
    2857    "A view that can only be visited by staff. Non staff members get an exception"
    2958    if request.user.is_staff:
    3059        return HttpResponse('')
    3160    else:
    3261        raise SuspiciousOperation()
    33    
     62
    3463def get_view(request):
    3564    "A simple login protected view"
    3665    return HttpResponse("Hello world")
  • tests/regressiontests/test_client_regress/models.py

     
    66from django.core.urlresolvers import reverse
    77from django.core.exceptions import SuspiciousOperation
    88import os
     9import sha
    910
    1011class AssertContainsTests(TestCase):
    1112    def test_contains(self):
     
    250251        response = self.client.post('/test_client_regress/file_upload/', post_data)
    251252        self.assertEqual(response.status_code, 200)
    252253
     254    def test_large_upload(self):
     255        import tempfile
     256        dir = tempfile.gettempdir()
     257
     258        (fd, name1) = tempfile.mkstemp(suffix='.file1', dir=dir)
     259        file1 = os.fdopen(fd, 'w+b')
     260        file1.write('a' * (2 ** 21))
     261        file1.seek(0)
     262
     263        (fd, name2) = tempfile.mkstemp(suffix='.file2', dir=dir)
     264        file2 = os.fdopen(fd, 'w+b')
     265        file2.write('a' * (10 * 2 ** 20))
     266        file2.seek(0)
     267
     268        # This file contains chinese symbols for a name.
     269        name3 = os.path.join(dir, u'test_&#20013;&#25991;_Orl\u00e9ans.jpg')
     270        file3 = open(name3, 'w+b')
     271        file3.write('b' * (2 ** 10))
     272        file3.seek(0)
     273
     274        post_data = {
     275            'name': 'Ringo',
     276            'file_field1': file1,
     277            'file_field2': file2,
     278            'file_unicode': file3,
     279            }
     280
     281        for key in post_data.keys():
     282            try:
     283                post_data[key + '_hash'] = sha.new(post_data[key].read()).hexdigest()
     284                post_data[key].seek(0)
     285            except AttributeError:
     286                post_data[key + '_hash'] = sha.new(post_data[key]).hexdigest()
     287
     288        response = self.client.post('/test_client_regress/file_upload_verify/', post_data)
     289
     290        for name in (name1, name2, name3):
     291            try:
     292                os.unlink(name)
     293            except:
     294                pass
     295
     296        self.assertEqual(response.status_code, 200)
     297
    253298class LoginTests(TestCase):
    254299    fixtures = ['testdata']
    255300
  • tests/regressiontests/test_client_regress/urls.py

     
    44urlpatterns = patterns('',
    55    (r'^no_template_view/$', views.no_template_view),
    66    (r'^file_upload/$', views.file_upload_view),
     7    (r'^file_upload_verify/$', views.file_upload_view_verify),
    78    (r'^staff_only/$', views.staff_only_view),
    89    (r'^get_view/$', views.get_view),
    910    url(r'^arg_view/(?P<name>.+)/$', views.view_with_argument, name='arg_view'),
  • tests/regressiontests/datastructures/tests.py

     
    117117>>> d['person']['2']['firstname']
    118118['Adrian']
    119119
    120 ### FileDict ################################################################
    121 
    122 >>> d = FileDict({'content': 'once upon a time...'})
     120### ImmutableList ################################################################
     121>>> d = ImmutableList(range(10))
     122>>> d.sort()
     123Traceback (most recent call last):
     124  File "<stdin>", line 1, in <module>
     125  File "/var/lib/python-support/python2.5/django/utils/datastructures.py", line 359, in complain
     126    raise AttributeError, self.warning
     127AttributeError: ImmutableList object is immutable.
    123128>>> repr(d)
    124 "{'content': '<omitted>'}"
    125 >>> d = FileDict({'other-key': 'once upon a time...'})
    126 >>> repr(d)
    127 "{'other-key': 'once upon a time...'}"
     129'(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)'
     130>>> d = ImmutableList(range(10), warning="Object is immutable!")
     131>>> d[1]
     1321
     133>>> d[1] = 'test'
     134Traceback (most recent call last):
     135  File "<stdin>", line 1, in <module>
     136  File "/var/lib/python-support/python2.5/django/utils/datastructures.py", line 359, in complain
     137    raise AttributeError, self.warning
     138AttributeError: Object is immutable!
    128139"""
  • AUTHORS

     
    5959    Arthur <avandorp@gmail.com>
    6060    av0000@mail.ru
    6161    David Avsajanishvili <avsd05@gmail.com>
    62     axiak@mit.edu
     62    Mike Axiak <axiak@mit.edu>
    6363    Niran Babalola <niran@niran.org>
    6464    Morten Bagai <m@bagai.com>
    6565    Mikaël Barbero <mikael.barbero nospam at nospam free.fr>
     
    139139    Marc Fargas <telenieko@telenieko.com>
    140140    Szilveszter Farkas <szilveszter.farkas@gmail.com>
    141141    favo@exoweb.net
     142    fdr <drfarina@gmail.com>
    142143    Dmitri Fedortchenko <zeraien@gmail.com>
    143144    Liang Feng <hutuworm@gmail.com>
    144145    Bill Fenner <fenner@gmail.com>
  • docs/request_response.txt

     
    8080    strings.
    8181
    8282``FILES``
     83   **New in Django development version**
    8384    A dictionary-like object containing all uploaded files. Each key in
    8485    ``FILES`` is the ``name`` from the ``<input type="file" name="" />``. Each
    85     value in ``FILES`` is a standard Python dictionary with the following three
    86     keys:
     86    value in ``FILES`` is an ``UploadedFile`` object containing at least the
     87    following attributes:
    8788
    88         * ``filename`` -- The name of the uploaded file, as a Python string.
    89         * ``content-type`` -- The content type of the uploaded file.
    90         * ``content`` -- The raw content of the uploaded file.
     89        * ``read(num_bytes=None)`` -- Read a number of bytes from the file.
     90        * ``file_name`` -- The name of the uploaded file.
     91        * ``file_size`` -- The size, in bytes, of the uploaded file.
     92        * ``chunk()`` -- A generator that yields sequential chunks of data.
    9193
    92     Note that ``FILES`` will only contain data if the request method was POST
    93     and the ``<form>`` that posted to the request had
    94     ``enctype="multipart/form-data"``. Otherwise, ``FILES`` will be a blank
    95     dictionary-like object.
     94    See `File Uploads`_ for more information. Note that ``FILES`` will only
     95    contain data if the request method was POST and the ``<form>`` that posted
     96    to the request had ``enctype="multipart/form-data"``. Otherwise, ``FILES``
     97    will be a blank dictionary-like object.
    9698
     99    .. _File Uploads: ../upload_handling/
     100
    97101``META``
    98102    A standard Python dictionary containing all available HTTP headers.
    99103    Available headers depend on the client and server, but here are some
  • docs/settings.txt

     
    279279
    280280The database backend to use. The build-in database backends are
    281281``'postgresql_psycopg2'``, ``'postgresql'``, ``'mysql'``, ``'mysql_old'``,
    282 ``'sqlite3'`` and ``'oracle'``.
     282``'sqlite3'``, ``'oracle'``, and ``'oracle'``.
    283283
    284284In the Django development version, you can use a database backend that doesn't
    285285ship with Django by setting ``DATABASE_ENGINE`` to a fully-qualified path (i.e.
     
    523523The character encoding used to decode any files read from disk. This includes
    524524template files and initial SQL data files.
    525525
     526FILE_UPLOAD_HANDLERS
     527--------------------
     528
     529**New in Django development version**
     530
     531Default::
     532
     533    ("django.core.files.fileuploadhandler.MemoryFileUploadHandler",
     534     "django.core.files.fileuploadhandler.TemporaryFileUploadHandler",)
     535
     536A tuple of handlers to use for uploading.
     537
     538FILE_UPLOAD_MAX_MEMORY_SIZE
     539---------------------------
     540
     541**New in Django development version**
     542
     543Default: ``2621440``
     544
     545The maximum size (in bytes) that an upload will be before it gets streamed to the file system.
     546
     547FILE_UPLOAD_TEMP_DIR
     548--------------------
     549
     550**New in Django development version**
     551
     552Default: ``None``
     553
     554The directory to store data temporarily while uploading files. If ``None``, Django will use the standard temporary directory for the operating system. For example, this will default to '/tmp' on *nix-style operating systems.
     555
    526556FIXTURE_DIRS
    527557-------------
    528558
  • docs/newforms.txt

     
    805805need to bind the file data containing the mugshot image::
    806806
    807807    # Bound form with an image field
     808    >>> from django.core.files.uploadedfile import SimpleUploadedFile
    808809    >>> data = {'subject': 'hello',
    809810    ...         'message': 'Hi there',
    810811    ...         'sender': 'foo@example.com',
    811812    ...         'cc_myself': True}
    812     >>> file_data = {'mugshot': {'filename':'face.jpg'
    813     ...                          'content': <file data>}}
     813    >>> file_data = {'mugshot': SimpleUploadedFile('face.jpg', <file data>)}
    814814    >>> f = ContactFormWithMugshot(data, file_data)
    815815
    816816In practice, you will usually specify ``request.FILES`` as the source
Back to Top