Ticket #3297: 4700-newforms-file-imagefield.2.diff
File 4700-newforms-file-imagefield.2.diff, 11.6 KB (added by , 18 years ago) |
---|
-
django/db/models/fields/__init__.py
662 662 else: 663 663 func(new_data[upload_field_name]["filename"], new_data[upload_field_name]["content"], save) 664 664 665 def formfield_save_file(self, field_name, new_data, new_object, save=True): 666 if new_data[field_name][0]: 667 func = getattr(new_object, 'save_%s_file' % self.name) 668 func(new_data[field_name][0]["filename"], new_data[field_name][0]["content"], save) 669 665 670 def get_directory_name(self): 666 671 return os.path.normpath(datetime.datetime.now().strftime(self.upload_to)) 667 672 … … 670 675 f = os.path.join(self.get_directory_name(), get_valid_filename(os.path.basename(filename))) 671 676 return os.path.normpath(f) 672 677 678 def formfield(self, **kwargs): 679 defaults = {'required': not self.blank, 'label': capfirst(self.verbose_name), 'widget': forms.FileInput} 680 defaults.update(kwargs) 681 return forms.FileField(**defaults) 682 673 683 class FilePathField(Field): 674 684 def __init__(self, verbose_name=None, name=None, path='', match=None, recursive=False, **kwargs): 675 685 self.path, self.match, self.recursive = path, match, recursive … … 716 726 setattr(new_object, self.height_field, getattr(original_object, self.height_field)) 717 727 new_object.save() 718 728 729 def formfield(self, **kwargs): 730 defaults = {'required': not self.blank, 'label': capfirst(self.verbose_name), 'widget': forms.FileInput} 731 defaults.update(kwargs) 732 return forms.ImageField(**defaults) 733 719 734 class IntegerField(Field): 720 735 empty_strings_allowed = False 721 736 def get_manipulator_field_objs(self): -
django/newforms/models.py
18 18 19 19 This method is created for any form_for_model Form. 20 20 """ 21 from django.db import models 21 22 if self.errors: 22 23 raise ValueError("The %s could not be created because the data didn't validate." % self._model._meta.object_name) 23 24 return save_instance(self, self._model(), commit) … … 36 37 raise ValueError("The %s could not be changed because the data didn't validate." % opts.object_name) 37 38 clean_data = form.clean_data 38 39 for f in opts.fields: 39 if not f.editable or isinstance(f, models.AutoField): 40 continue 41 setattr(instance, f.name, clean_data[f.name]) 40 if clean_data.has_key(f.name): 41 if not f.editable or isinstance(f, models.AutoField): 42 continue 43 if isinstance(f, models.FileField): 44 continue 45 setattr(instance, f.name, clean_data[f.name]) 46 47 # FileField may need more info to save to specific paths 48 for f in opts.fields: 49 if isinstance(f, models.FileField) and clean_data.has_key(f.name): 50 f.formfield_save_file(f.name, clean_data, instance, save=False) 51 42 52 if commit: 43 53 instance.save() 44 54 for f in opts.many_to_many: -
django/newforms/fields.py
10 10 import time 11 11 12 12 __all__ = ( 13 'Field', 'CharField', ' IntegerField',13 'Field', 'CharField', 'FileField', 'ImageField', 'IntegerField', 14 14 'DEFAULT_DATE_INPUT_FORMATS', 'DateField', 15 15 'DEFAULT_TIME_INPUT_FORMATS', 'TimeField', 16 16 'DEFAULT_DATETIME_INPUT_FORMATS', 'DateTimeField', … … 107 107 if self.max_length is not None and isinstance(widget, (TextInput, PasswordInput)): 108 108 return {'maxlength': str(self.max_length)} 109 109 110 class FileField(Field): 111 112 prev_error = False 113 114 def clean(self, value): 115 super(FileField, self).clean(value) 116 117 if value[0]: 118 try: 119 content = value[0]['content'] 120 except TypeError: 121 self.prev_error = True 122 raise ValidationError(gettext("No file was submitted. Check the encoding type on the form.")) 123 124 if not content: 125 self.prev_error = True 126 raise ValidationError(gettext(u'The submitted file is empty.')) 127 128 elif self.required: 129 if not value[1]: 130 self.prev_error = True 131 raise ValidationError(gettext(u'This field is required.')) 132 133 return value 134 135 class ImageField(FileField): 136 137 def clean(self, value): 138 super(ImageField, self).clean(value) 139 if value[0] and not self.prev_error: 140 from PIL import Image 141 from cStringIO import StringIO 142 try: 143 Image.open(StringIO(value[0]['content'])) 144 except IOError: # Python Imaging Library doesn't recognize it as an image 145 raise ValidationError, gettext(u'Upload a valid image. The file you uploaded was either not an image or a corrupted image.') 146 return value 147 110 148 class IntegerField(Field): 111 149 def __init__(self, max_value=None, min_value=None, *args, **kwargs): 112 150 self.max_value, self.min_value = max_value, min_value -
django/newforms/widgets.py
115 115 116 116 class FileInput(Input): 117 117 input_type = 'file' 118 119 def render(self,name,value,attrs=None,choices=()): 120 if value is None: value = '' 121 file_attrs = self.build_attrs(attrs, type='file', name=name+'_file') 122 final_attrs = self.build_attrs(attrs, type='hidden', name=name) 123 if value != '': final_attrs['value'] = smart_unicode(value) # only add the value attribute if a value is non-empty 124 125 if value != '': 126 currently = u'Currently: %s<br/>Change: ' % smart_unicode(value) 127 current = u' <input%s />' % flatatt(final_attrs) 128 else: 129 currently = u'' 130 current = u'' 131 132 return u'%s<input%s />%s' % (currently,flatatt(file_attrs),current) 133 134 def value_from_datadict(self,data,name): 135 return [data.get(name+'_file',None),data.get(name,None)] 118 136 119 137 class Textarea(Widget): 120 138 def render(self, name, value, attrs=None): -
tests/modeltests/model_forms/models.py
61 61 def __str__(self): 62 62 return self.phone 63 63 64 class NotRequiredFile(models.Model): 65 description = models.CharField(maxlength=50) 66 file = models.FileField(upload_to='files', blank=True) 67 68 def __str__(self): 69 return self.description 70 71 class RequiredFile(models.Model): 72 description = models.CharField(maxlength=50) 73 file = models.FileField(upload_to='files') 74 75 def __str__(self): 76 return self.description 77 64 78 __test__ = {'API_TESTS': """ 65 79 >>> from django.newforms import form_for_model, form_for_instance, save_instance, BaseForm, Form, CharField 66 80 >>> import datetime … … 377 391 378 392 >>> f = ModelChoiceField(Category.objects.filter(pk=1), required=False) 379 393 >>> print f.clean('') 394 395 Test for filefield 396 397 >>> form_data = {'description': 'FileField test', 'file_file': {'content': 'FileField test', 'filename': 'filetest.txt'} } 398 >>> no_file_form_data = {'description': 'FileField test'} 399 >>> just_path_form_data = {'description': 'FileField test', 'file': 'files/filetest.txt'} 400 >>> bad_encoding_form_data = {'description': 'FileField test', 'file': 'files/filetest.txt', 'file_file': 'wrong encoding'} 401 >>> TestRequiredFileForm = form_for_model(RequiredFile) 402 >>> empty_required_fileform = TestRequiredFileForm(auto_id=False) 403 >>> print empty_required_fileform.as_ul() 404 <li>Description: <input type="text" name="description" maxlength="50" /></li> 405 <li>File: <input type="file" name="file_file" /></li> 406 407 Test with data 408 >>> filled_required_fileform= TestRequiredFileForm(form_data, auto_id=False) 409 >>> filled_required_fileform.is_valid() 410 True 411 412 >>> required_file_instance = filled_required_fileform.save() 413 >>> print required_file_instance.file 414 files/filetest.txt 415 >>> TestInstanceRequiredFileForm = form_for_instance(required_file_instance) 416 >>> instance_required_fileform = TestInstanceRequiredFileForm(auto_id=False) 417 >>> instance_required_fileform.as_ul() 418 u'<li>Description: <input type="text" name="description" value="FileField test" maxlength="50" /></li>\\n<li>File: Currently: files/filetest.txt<br/>Change: <input type="file" name="file_file" /> <input type="hidden" name="file" value="files/filetest.txt" /></li>' 419 >>> required_file_instance.delete() 420 421 Bad data test 422 >>> filled_required_fileform=TestRequiredFileForm(no_file_form_data) 423 >>> filled_required_fileform.is_valid() 424 False 425 >>> print filled_required_fileform.errors 426 <ul class="errorlist"><li>file<ul class="errorlist"><li>This field is required.</li></ul></li></ul> 427 >>> TestNotRequiredFileForm = form_for_model(NotRequiredFile) 428 >>> filled_not_required_fileform=TestNotRequiredFileForm(no_file_form_data) 429 >>> filled_not_required_fileform.is_valid() 430 True 431 >>> filled_not_required_fileform=TestNotRequiredFileForm(bad_encoding_form_data) 432 >>> print filled_not_required_fileform.errors 433 <ul class="errorlist"><li>file<ul class="errorlist"><li>No file was submitted. Check the encoding type on the form.</li></ul></li></ul> 434 >>> filled_not_required_fileform=TestNotRequiredFileForm(just_path_form_data) 435 >>> filled_not_required_fileform.is_valid() 436 True 437 >>> filled_required_fileform=TestRequiredFileForm(just_path_form_data) 438 >>> filled_required_fileform.is_valid() 439 True 380 440 None 381 441 >>> f.clean('') 382 442 >>> f.clean('1') -
tests/regressiontests/forms/tests.py
165 165 # FileInput Widget ############################################################ 166 166 167 167 >>> w = FileInput() 168 >>> w.render('email', '') 169 u'<input type="file" name="email" />' 170 >>> w.render('email', None) 171 u'<input type="file" name="email" />' 172 >>> w.render('email', 'test@example.com') 173 u'<input type="file" name="email" value="test@example.com" />' 174 >>> w.render('email', 'some "quoted" & ampersanded value') 175 u'<input type="file" name="email" value="some "quoted" & ampersanded value" />' 176 >>> w.render('email', 'test@example.com', attrs={'class': 'fun'}) 177 u'<input type="file" name="email" value="test@example.com" class="fun" />' 168 >>> w.render('file', '') 169 u'<input type="file" name="file_file" />' 170 >>> w.render('file', 'file/filetest.txt') 171 u'Currently: file/filetest.txt<br/>Change: <input type="file" name="file_file" /> <input type="hidden" name="file" value="file/filetest.txt" />' 178 172 179 You can also pass 'attrs' to the constructor:180 >>> w = FileInput(attrs={'class': 'fun'})181 >>> w.render('email', '')182 u'<input type="file" class="fun" name="email" />'183 >>> w.render('email', 'foo@example.com')184 u'<input type="file" class="fun" value="foo@example.com" name="email" />'185 186 >>> w.render('email', 'ŠĐĆŽćžšđ', attrs={'class': 'fun'})187 u'<input type="file" class="fun" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" name="email" />'188 189 173 # Textarea Widget ############################################################# 190 174 191 175 >>> w = Textarea()