Ticket #3297: 5245-newforms-file-imagefield.diff
File 5245-newforms-file-imagefield.diff, 11.0 KB (added by , 17 years ago) |
---|
-
django/db/models/fields/__init__.py
==== Patch <django-newforms-file-imagefield> level 3 Source: f4626db1-382e-0410-8594-a82d82b39f71:/newforms-file-imagefield/trunk:5184 [local] Target: bcc190cf-cafb-0310-a4f2-bffc1f526a37:/django/trunk:5245 [mirrored] (http://code.djangoproject.com/svn/django) Log: r4876@damasonium: ddanier | 2007-04-16 14:26:42 +0200 * FileField and ImageField for newforms not using additional <input>'s * FileInput is now the default-widget for FileField r5183@damasonium: ddanier | 2007-05-15 17:25:46 +0200 * Updated models.FileField and models.ImageField to use new formfield()-base in Field-class r5184@damasonium: ddanier | 2007-05-15 17:33:03 +0200 * clean_data -> cleaned_data === django/db/models/fields/__init__.py ==================================================================
665 665 else: 666 666 func(new_data[upload_field_name]["filename"], new_data[upload_field_name]["content"], save) 667 667 668 def formfield_save_file(self, field_name, new_data, new_object, save=True): 669 if new_data[field_name]: 670 func = getattr(new_object, 'save_%s_file' % self.name) 671 func(new_data[field_name]["filename"], new_data[field_name]["content"], save) 672 668 673 def get_directory_name(self): 669 674 return os.path.normpath(datetime.datetime.now().strftime(self.upload_to)) 670 675 … … 673 678 f = os.path.join(self.get_directory_name(), get_valid_filename(os.path.basename(filename))) 674 679 return os.path.normpath(f) 675 680 681 def formfield(self, **kwargs): 682 defaults = {'form_class': forms.FileField} 683 defaults.update(kwargs) 684 return super(FileField, self).formfield(**defaults) 685 676 686 class FilePathField(Field): 677 687 def __init__(self, verbose_name=None, name=None, path='', match=None, recursive=False, **kwargs): 678 688 self.path, self.match, self.recursive = path, match, recursive … … 719 729 setattr(new_object, self.height_field, getattr(original_object, self.height_field)) 720 730 new_object.save() 721 731 732 def formfield(self, **kwargs): 733 defaults = {'form_class': forms.ImageField} 734 defaults.update(kwargs) 735 return super(ImageField, self).formfield(**defaults) 736 722 737 class IntegerField(Field): 723 738 empty_strings_allowed = False 724 739 def get_manipulator_field_objs(self): -
django/newforms/models.py
=== django/newforms/models.py ==================================================================
28 28 for f in opts.fields: 29 29 if not f.editable or isinstance(f, models.AutoField) or not f.name in cleaned_data: 30 30 continue 31 if isinstance(f, models.FileField): 32 continue 31 33 if fields and f.name not in fields: 32 34 continue 33 35 setattr(instance, f.name, cleaned_data[f.name]) 36 37 # FileField may need more info to save to specific paths 38 for f in opts.fields: 39 if isinstance(f, models.FileField) and cleaned_data.has_key(f.name): 40 f.formfield_save_file(f.name, cleaned_data, instance, save=False) 41 34 42 if commit: 35 43 instance.save() 36 44 for f in opts.many_to_many: … … 91 99 takes a database Field instance, plus **kwargs, and returns a form Field 92 100 instance with the given kwargs (i.e. 'initial'). 93 101 """ 102 from django.db import models 94 103 model = instance.__class__ 95 104 opts = model._meta 96 105 field_list = [] … … 102 111 current_value = f.value_from_object(instance) 103 112 formfield = formfield_callback(f, initial=current_value) 104 113 if formfield: 114 # FileFields are only required once, because we cannot print the 115 # existing data into the <form> 116 if isinstance(f, models.FileField) and current_value: 117 formfield.required = False 105 118 field_list.append((f.name, formfield)) 106 119 base_fields = SortedDictFromList(field_list) 107 120 return type(opts.object_name + 'InstanceForm', (form,), -
django/newforms/fields.py
=== django/newforms/fields.py ==================================================================
5 5 from django.utils.translation import gettext 6 6 from django.utils.encoding import smart_unicode 7 7 from util import ErrorList, ValidationError 8 from widgets import TextInput, PasswordInput, HiddenInput, MultipleHiddenInput, CheckboxInput, Select, NullBooleanSelect, SelectMultiple 8 from widgets import TextInput, PasswordInput, HiddenInput, MultipleHiddenInput, CheckboxInput, Select, NullBooleanSelect, SelectMultiple, FileInput 9 9 import datetime 10 10 import re 11 11 import time 12 12 13 13 __all__ = ( 14 'Field', 'CharField', ' IntegerField',14 'Field', 'CharField', 'FileField', 'ImageField', 'IntegerField', 15 15 'DEFAULT_DATE_INPUT_FORMATS', 'DateField', 16 16 'DEFAULT_TIME_INPUT_FORMATS', 'TimeField', 17 17 'DEFAULT_DATETIME_INPUT_FORMATS', 'DateTimeField', … … 109 109 if self.max_length is not None and isinstance(widget, (TextInput, PasswordInput)): 110 110 return {'maxlength': str(self.max_length)} 111 111 112 class FileField(Field): 113 widget = FileInput 114 115 def clean(self, value): 116 super(FileField, self).clean(value) 117 if value in EMPTY_VALUES: 118 return None 119 else: 120 try: 121 content = value['content'] 122 except TypeError: 123 raise ValidationError(gettext("No file was submitted. Check the encoding type on the form.")) 124 if not content: 125 raise ValidationError(gettext(u'The submitted file is empty.')) 126 return value 127 128 class ImageField(FileField): 129 def clean(self, value): 130 super(ImageField, self).clean(value) 131 if value in EMPTY_VALUES: 132 return None 133 else: 134 from PIL import Image 135 from cStringIO import StringIO 136 try: 137 Image.open(StringIO(value['content'])) 138 except IOError: # Python Imaging Library doesn't recognize it as an image 139 raise ValidationError, gettext(u'Upload a valid image. The file you uploaded was either not an image or a corrupted image.') 140 return value 141 112 142 class IntegerField(Field): 113 143 def __init__(self, max_value=None, min_value=None, *args, **kwargs): 114 144 self.max_value, self.min_value = max_value, min_value -
tests/modeltests/model_forms/models.py
=== tests/modeltests/model_forms/models.py ==================================================================
68 68 def __str__(self): 69 69 return self.phone 70 70 71 class NotRequiredFile(models.Model): 72 description = models.CharField(maxlength=50) 73 file = models.FileField(upload_to='files', blank=True) 74 75 def __str__(self): 76 return self.description 77 78 class RequiredFile(models.Model): 79 description = models.CharField(maxlength=50) 80 file = models.FileField(upload_to='files') 81 82 def __str__(self): 83 return self.description 84 71 85 __test__ = {'API_TESTS': """ 72 86 >>> from django.newforms import form_for_model, form_for_instance, save_instance, BaseForm, Form, CharField 73 87 >>> import datetime … … 442 456 443 457 >>> f = ModelChoiceField(Category.objects.filter(pk=1), required=False) 444 458 >>> print f.clean('') 459 460 Test for filefield 461 462 >>> form_data = {'description': 'FileField test', 'file': {'content': 'FileField test', 'filename': 'filetest.txt'} } 463 >>> no_file_form_data = {'description': 'FileField test'} 464 >>> bad_encoding_form_data = {'description': 'FileField test', 'file': 'wrong encoding'} 465 >>> TestRequiredFileForm = form_for_model(RequiredFile) 466 >>> empty_required_fileform = TestRequiredFileForm(auto_id=False) 467 >>> print empty_required_fileform.as_ul() 468 <li>Description: <input type="text" name="description" maxlength="50" /></li> 469 <li>File: <input type="file" name="file" /></li> 470 471 Test with data 472 >>> filled_required_fileform= TestRequiredFileForm(form_data, auto_id=False) 473 >>> filled_required_fileform.is_valid() 474 True 475 476 >>> required_file_instance = filled_required_fileform.save() 477 >>> print required_file_instance.file 478 files/filetest.txt 479 >>> TestInstanceRequiredFileForm = form_for_instance(required_file_instance) 480 >>> instance_required_fileform = TestInstanceRequiredFileForm(auto_id=False) 481 >>> instance_required_fileform.as_ul() 482 u'<li>Description: <input type="text" name="description" value="FileField test" maxlength="50" /></li>\\n<li>File: <input type="file" name="file" /></li>' 483 >>> required_file_instance.delete() 484 485 Bad data test 486 >>> filled_required_fileform=TestRequiredFileForm(no_file_form_data) 487 >>> filled_required_fileform.is_valid() 488 False 489 >>> print filled_required_fileform.errors 490 <ul class="errorlist"><li>file<ul class="errorlist"><li>This field is required.</li></ul></li></ul> 491 >>> TestNotRequiredFileForm = form_for_model(NotRequiredFile) 492 >>> filled_not_required_fileform=TestNotRequiredFileForm(no_file_form_data) 493 >>> filled_not_required_fileform.is_valid() 494 True 495 >>> filled_not_required_fileform=TestNotRequiredFileForm(bad_encoding_form_data) 496 >>> print filled_not_required_fileform.errors 497 <ul class="errorlist"><li>file<ul class="errorlist"><li>No file was submitted. Check the encoding type on the form.</li></ul></li></ul> 445 498 None 446 499 >>> f.clean('') 447 500 >>> f.clean('1') -
tests/regressiontests/forms/tests.py
=== tests/regressiontests/forms/tests.py ==================================================================
169 169 # FileInput Widget ############################################################ 170 170 171 171 >>> w = FileInput() 172 >>> w.render('email', '') 173 u'<input type="file" name="email" />' 174 >>> w.render('email', None) 175 u'<input type="file" name="email" />' 176 >>> w.render('email', 'test@example.com') 177 u'<input type="file" name="email" value="test@example.com" />' 178 >>> w.render('email', 'some "quoted" & ampersanded value') 179 u'<input type="file" name="email" value="some "quoted" & ampersanded value" />' 180 >>> w.render('email', 'test@example.com', attrs={'class': 'fun'}) 181 u'<input type="file" name="email" value="test@example.com" class="fun" />' 172 >>> w.render('file', '') 173 u'<input type="file" name="file" />' 182 174 183 You can also pass 'attrs' to the constructor:184 >>> w = FileInput(attrs={'class': 'fun'})185 >>> w.render('email', '')186 u'<input type="file" class="fun" name="email" />'187 >>> w.render('email', 'foo@example.com')188 u'<input type="file" class="fun" value="foo@example.com" name="email" />'189 190 >>> w.render('email', 'ŠĐĆŽćžšđ', attrs={'class': 'fun'})191 u'<input type="file" class="fun" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" name="email" />'192 193 175 # Textarea Widget ############################################################# 194 176 195 177 >>> w = Textarea()