Django

Code

Changeset 7858

Show
Ignore:
Timestamp:
07/07/08 17:06:32 (5 months ago)
Author:
jacob
Message:

Fixed #7651: uploading multiple files with the same name now work. Also, in order to test the problem the test client now handles uploading multiple files at once. Patch from Mike Axiak.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/trunk/django/http/multipartparser.py

    r7814 r7858  
    137137                    # we hit the next boundary/part of the multipart content. 
    138138                    self.handle_file_complete(old_field_name, counters) 
     139                    old_field_name = None 
    139140 
    140141                try: 
  • django/trunk/django/test/client.py

    r7821 r7858  
    9191    lines = [] 
    9292    to_str = lambda s: smart_str(s, settings.DEFAULT_CHARSET) 
     93 
     94    # Not by any means perfect, but good enough for our purposes. 
     95    is_file = lambda thing: hasattr(thing, "read") and callable(thing.read) 
     96 
     97    # Each bit of the multipart form data could be either a form value or a 
     98    # file, or a *list* of form values and/or files. Remember that HTTP field 
     99    # names can be duplicated! 
    93100    for (key, value) in data.items(): 
    94         if isinstance(value, file): 
    95             lines.extend([ 
    96                 '--' + boundary, 
    97                 'Content-Disposition: form-data; name="%s"; filename="%s"' \ 
    98                     % (to_str(key), to_str(os.path.basename(value.name))), 
    99                 'Content-Type: application/octet-stream', 
    100                 '', 
    101                 value.read() 
    102             ]) 
    103         else: 
    104             if not isinstance(value, basestring) and is_iterable(value): 
    105                 for item in value: 
     101        if is_file(value): 
     102            lines.extend(encode_file(boundary, key, value)) 
     103        elif not isinstance(value, basestring) and is_iterable(value): 
     104            for item in value: 
     105                if is_file(item): 
     106                    lines.extend(encode_file(boundary, key, item)) 
     107                else: 
    106108                    lines.extend([ 
    107109                        '--' + boundary, 
     
    110112                        to_str(item) 
    111113                    ]) 
    112             else: 
    113                 lines.extend([ 
    114                     '--' + boundary, 
    115                     'Content-Disposition: form-data; name="%s"' % to_str(key), 
    116                     '', 
    117                     to_str(value) 
    118                 ]) 
     114        else: 
     115            lines.extend([ 
     116                '--' + boundary, 
     117                'Content-Disposition: form-data; name="%s"' % to_str(key), 
     118                '', 
     119                to_str(value) 
     120            ]) 
    119121 
    120122    lines.extend([ 
     
    124126    return '\r\n'.join(lines) 
    125127 
     128def encode_file(boundary, key, file): 
     129    to_str = lambda s: smart_str(s, settings.DEFAULT_CHARSET) 
     130    return [ 
     131        '--' + boundary, 
     132        'Content-Disposition: form-data; name="%s"; filename="%s"' \ 
     133            % (to_str(key), to_str(os.path.basename(file.name))), 
     134        'Content-Type: application/octet-stream', 
     135        '', 
     136        file.read() 
     137    ] 
     138     
    126139class Client: 
    127140    """ 
  • django/trunk/tests/regressiontests/file_uploads/tests.py

    r7814 r7858  
    148148        f = tempfile.NamedTemporaryFile() 
    149149        f.write('a' * (2 ** 21)) 
    150          
     150 
    151151        # AttributeError: You cannot alter upload handlers after the upload has been processed. 
    152152        self.assertRaises( 
    153153            AttributeError, 
    154154            self.client.post, 
    155             '/file_uploads/quota/broken/',  
     155            '/file_uploads/quota/broken/', 
    156156            {'f': open(f.name)} 
    157         )         
    158          
     157        ) 
     158 
     159    def test_fileupload_getlist(self): 
     160        file1 = tempfile.NamedTemporaryFile() 
     161        file1.write('a' * (2 ** 23)) 
     162 
     163        file2 = tempfile.NamedTemporaryFile() 
     164        file2.write('a' * (2 * 2 ** 18)) 
     165 
     166        file2a = tempfile.NamedTemporaryFile() 
     167        file2a.write('a' * (5 * 2 ** 20)) 
     168 
     169        response = self.client.post('/file_uploads/getlist_count/', { 
     170            'file1': open(file1.name), 
     171            'field1': u'test', 
     172            'field2': u'test3', 
     173            'field3': u'test5', 
     174            'field4': u'test6', 
     175            'field5': u'test7', 
     176            'file2': (open(file2.name), open(file2a.name)) 
     177        }) 
     178        got = simplejson.loads(response.content) 
     179 
     180        self.assertEqual(got.get('file1'), 1) 
     181        self.assertEqual(got.get('file2'), 2) 
  • django/trunk/tests/regressiontests/file_uploads/urls.py

    r7814 r7858  
    88    (r'^quota/$',           views.file_upload_quota), 
    99    (r'^quota/broken/$',    views.file_upload_quota_broken), 
     10    (r'^getlist_count/$',   views.file_upload_getlist_count), 
    1011) 
  • django/trunk/tests/regressiontests/file_uploads/views.py

    r7814 r7858  
    6969    request.upload_handlers.insert(0, QuotaUploadHandler()) 
    7070    return response 
     71 
     72def file_upload_getlist_count(request): 
     73    """ 
     74    Check the .getlist() function to ensure we receive the correct number of files. 
     75    """ 
     76    file_counts = {} 
     77 
     78    for key in request.FILES.keys(): 
     79        file_counts[key] = len(request.FILES.getlist(key)) 
     80    return HttpResponse(simplejson.dumps(file_counts))