Ticket #6302: pass_initial_through_with_tests_mulitvaluefield.diff
File pass_initial_through_with_tests_mulitvaluefield.diff, 15.2 KB (added by , 17 years ago) |
---|
-
django/db/models/fields/__init__.py
797 797 return os.path.normpath(f) 798 798 799 799 def save_form_data(self, instance, data): 800 if data: 800 from django.newforms.fields import UploadedFile 801 if data and isinstance(data, UploadedFile): 801 802 getattr(instance, "save_%s_file" % self.name)(data.filename, data.content, save=False) 802 803 803 804 def formfield(self, **kwargs): 804 805 defaults = {'form_class': forms.FileField} 805 # If a file has been provided previously, then the form doesn't require806 # that a new file is provided this time.807 if 'initial' in kwargs:808 defaults['required'] = False809 806 defaults.update(kwargs) 810 807 return super(FileField, self).formfield(**defaults) 811 808 -
django/newforms/fields.py
428 428 429 429 class FileField(Field): 430 430 widget = FileInput 431 takes_initial = True 431 432 default_error_messages = { 432 433 'invalid': _(u"No file was submitted. Check the encoding type on the form."), 433 434 'missing': _(u"No file was submitted."), … … 437 438 def __init__(self, *args, **kwargs): 438 439 super(FileField, self).__init__(*args, **kwargs) 439 440 440 def clean(self, data ):441 super(FileField, self).clean( data)441 def clean(self, data, initial=None): 442 super(FileField, self).clean(initial or data) 442 443 if not self.required and data in EMPTY_VALUES: 443 return None 444 return initial or None 445 elif not data and initial: 446 return initial 444 447 try: 445 448 f = UploadedFile(data['filename'], data['content']) 446 449 except TypeError: … … 456 459 'invalid_image': _(u"Upload a valid image. The file you uploaded was either not an image or a corrupted image."), 457 460 } 458 461 459 def clean(self, data ):462 def clean(self, data, initial=None): 460 463 """ 461 464 Checks that the file-upload field data contains a valid image (GIF, JPG, 462 465 PNG, possibly others -- whatever the Python Imaging Library supports). 463 466 """ 464 f = super(ImageField, self).clean(data )467 f = super(ImageField, self).clean(data, initial) 465 468 if f is None: 466 469 return None 467 470 from PIL import Image … … 614 617 return new_value 615 618 616 619 class ComboField(Field): 620 takes_initial = True 621 617 622 """ 618 623 A Field whose clean() method calls multiple Field clean() methods. 619 624 """ … … 626 631 f.required = False 627 632 self.fields = fields 628 633 629 def clean(self, value ):634 def clean(self, value, initial=None): 630 635 """ 631 636 Validates the given value against all of self.fields, which is a 632 637 list of Field instances. 633 638 """ 634 super(ComboField, self).clean( value)639 super(ComboField, self).clean(initial or value) 635 640 for field in self.fields: 636 value = field.clean(value) 641 if hasattr(field, 'takes_initial'): 642 value = field.clean(value, initial) 643 else: 644 value = field.clean(value) 637 645 return value 638 646 639 647 class MultiValueField(Field): … … 653 661 654 662 You'll probably want to use this with MultiWidget. 655 663 """ 664 takes_initial = True 656 665 default_error_messages = { 657 666 'invalid': _(u'Enter a list of values.'), 658 667 } … … 666 675 f.required = False 667 676 self.fields = fields 668 677 669 def clean(self, value ):678 def clean(self, value, initial=None): 670 679 """ 671 680 Validates every value in the given list. A value is validated against 672 681 the corresponding Field in self.fields. … … 675 684 fields=(DateField(), TimeField()), clean() would call 676 685 DateField.clean(value[0]) and TimeField.clean(value[1]). 677 686 """ 678 clean_data = [] 687 clean_data, value_list, initial_list, takes_initial_list = [], [], [], [] 688 value, initial = value or [], initial or [] 679 689 errors = ErrorList() 680 690 if not value or isinstance(value, (list, tuple)): 681 if not value or not [v for v in value if v not in EMPTY_VALUES]: 691 for i, field in enumerate(self.fields): 692 try: 693 field_value = value[i] 694 except IndexError: 695 field_value = None 696 value_list.append(field_value) 697 try: 698 field_initial = initial[i] 699 except IndexError: 700 field_initial = None 701 initial_list.append(field_initial) 702 takes_initial_list.append(hasattr(field, 'takes_initial')) 703 704 if not value or not [(v, i, t) for v, i, t in \ 705 zip(value_list, initial_list, takes_initial_list) \ 706 if v not in EMPTY_VALUES or t and i not in EMPTY_VALUES]: 707 682 708 if self.required: 683 709 raise ValidationError(self.error_messages['required']) 684 710 else: 685 711 return self.compress([]) 686 712 else: 687 713 raise ValidationError(self.error_messages['invalid']) 714 688 715 for i, field in enumerate(self.fields): 716 field_value = value_list[i] 717 field_initial = initial_list[i] 718 takes_initial = takes_initial_list[i] 719 if self.required and not ( (takes_initial and field_initial not in EMPTY_VALUES) or 720 (field_value not in EMPTY_VALUES) ): 721 raise ValidationError(self.error_messages['required']) 689 722 try: 690 field_value = value[i] 691 except IndexError: 692 field_value = None 693 if self.required and field_value in EMPTY_VALUES: 694 raise ValidationError(self.error_messages['required']) 695 try: 696 clean_data.append(field.clean(field_value)) 723 if takes_initial: 724 clean_data.append(field.clean(field_value, field_initial)) 725 else: 726 clean_data.append(field.clean(field_value)) 697 727 except ValidationError, e: 698 728 # Collect all validation errors in a single list, which we'll 699 729 # raise at the end of clean(), rather than raising a single … … 701 731 errors.extend(e.messages) 702 732 if errors: 703 733 raise ValidationError(errors) 704 return self.compress(clean_data )734 return self.compress(clean_data, initial_list) 705 735 706 def compress(self, data_list ):736 def compress(self, data_list, initial_list=[]): 707 737 """ 708 738 Returns a single value for the given list of values. The values can be 709 739 assumed to be valid. … … 730 760 ) 731 761 super(SplitDateTimeField, self).__init__(fields, *args, **kwargs) 732 762 733 def compress(self, data_list ):763 def compress(self, data_list, initial_list=[]): 734 764 if data_list: 735 765 # Raise a validation error if time or date is empty 736 766 # (possible if SplitDateTimeField has required=False). -
django/newforms/forms.py
182 182 # widgets split data over several HTML fields. 183 183 value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name)) 184 184 try: 185 value = field.clean(value) 185 if hasattr(field, 'takes_initial'): 186 initial = self.initial.get(name, field.initial) 187 value = field.clean(value, initial) 188 else: 189 value = field.clean(value) 186 190 self.cleaned_data[name] = value 187 191 if hasattr(self, 'clean_%s' % name): 188 192 value = getattr(self, 'clean_%s' % name)() -
tests/modeltests/model_forms/models.py
7 7 most of these tests should be rewritten. 8 8 """ 9 9 10 import os 11 import tempfile 12 10 13 from django.db import models 11 14 12 15 ARTICLE_STATUS = ( … … 55 58 def __unicode__(self): 56 59 return self.phone 57 60 61 class TextFile(models.Model): 62 description = models.CharField(max_length=20) 63 file = models.FileField(upload_to=tempfile.gettempdir()) 64 65 def __unicode__(self): 66 return self.description 67 58 68 __test__ = {'API_TESTS': """ 59 69 >>> from django import newforms as forms 60 70 >>> from django.newforms.models import ModelForm … … 701 711 True 702 712 >>> f.cleaned_data 703 713 {'phone': u'312-555-1212', 'description': u'Assistance'} 714 715 # FileField ################################################################### 716 717 >>> class TextFileForm(ModelForm): 718 ... class Meta: 719 ... model = TextFile 720 721 Test conditions when files is either not given or empty. 722 723 >>> f = TextFileForm(data={'description': u'Assistance'}) 724 >>> f.is_valid() 725 False 726 >>> f = TextFileForm(data={'description': u'Assistance'}, files={}) 727 >>> f.is_valid() 728 False 729 730 Upload a file and ensure it all works as expected. 731 732 >>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': {'filename': 'test1.txt', 'content': 'hello world'}}) 733 >>> f.is_valid() 734 True 735 >>> type(f.cleaned_data['file']) 736 <class 'django.newforms.fields.UploadedFile'> 737 >>> instance = f.save() 738 >>> instance.file 739 u'.../test1.txt' 740 741 Edit an instance that already has the file defined in the model. This will not 742 save the file again, but leave it exactly as it is. 743 744 >>> f = TextFileForm(data={'description': u'Assistance'}, instance=instance) 745 >>> f.is_valid() 746 True 747 >>> f.cleaned_data['file'] 748 u'.../test1.txt' 749 >>> instance = f.save() 750 >>> instance.file 751 u'.../test1.txt' 752 753 Delete the current file since this is not done by Django. 754 755 >>> os.unlink(instance.get_file_filename()) 756 757 Override the file by uploading a new one. 758 759 >>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': {'filename': 'test2.txt', 'content': 'hello world'}}, instance=instance) 760 >>> f.is_valid() 761 True 762 >>> instance = f.save() 763 >>> instance.file 764 u'.../test2.txt' 765 766 >>> instance.delete() 767 768 Test the non-required FileField 769 770 >>> f = TextFileForm(data={'description': u'Assistance'}) 771 >>> f.fields['file'].required = False 772 >>> f.is_valid() 773 True 774 >>> instance = f.save() 775 >>> instance.file 776 '' 777 778 >>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': {'filename': 'test3.txt', 'content': 'hello world'}}, instance=instance) 779 >>> f.is_valid() 780 True 781 >>> instance = f.save() 782 >>> instance.file 783 u'.../test3.txt' 784 >>> instance.delete() 704 785 """} -
tests/regressiontests/forms/extra.py
209 209 ... ) 210 210 ... super(ComplexField, self).__init__(fields, required, widget, label, initial) 211 211 ... 212 ... def compress(self, data_list ):212 ... def compress(self, data_list, initial_list=[]): 213 213 ... if data_list: 214 214 ... return '%s,%s,%s' % (data_list[0],''.join(data_list[1]),data_list[2]) 215 215 ... return None -
tests/regressiontests/forms/fields.py
749 749 ... 750 750 ValidationError: [u'This field is required.'] 751 751 752 >>> f.clean('', '') 753 Traceback (most recent call last): 754 ... 755 ValidationError: [u'This field is required.'] 756 757 >>> f.clean('', 'files/test1.pdf') 758 'files/test1.pdf' 759 752 760 >>> f.clean(None) 753 761 Traceback (most recent call last): 754 762 ... 755 763 ValidationError: [u'This field is required.'] 756 764 765 >>> f.clean(None, '') 766 Traceback (most recent call last): 767 ... 768 ValidationError: [u'This field is required.'] 769 770 >>> f.clean(None, 'files/test2.pdf') 771 'files/test2.pdf' 772 757 773 >>> f.clean({}) 758 774 Traceback (most recent call last): 759 775 ... 760 776 ValidationError: [u'No file was submitted.'] 761 777 778 >>> f.clean({}, '') 779 Traceback (most recent call last): 780 ... 781 ValidationError: [u'No file was submitted.'] 782 783 >>> f.clean({}, 'files/test3.pdf') 784 'files/test3.pdf' 785 762 786 >>> f.clean('some content that is not a file') 763 787 Traceback (most recent call last): 764 788 ... 765 789 ValidationError: [u'No file was submitted. Check the encoding type on the form.'] 766 790 767 >>> f.clean({'filename': 'name', 'content': None})791 >>> f.clean({'filename': 'name', 'content': None}) 768 792 Traceback (most recent call last): 769 793 ... 770 794 ValidationError: [u'The submitted file is empty.'] 771 795 772 >>> f.clean({'filename': 'name', 'content': ''})796 >>> f.clean({'filename': 'name', 'content': ''}) 773 797 Traceback (most recent call last): 774 798 ... 775 799 ValidationError: [u'The submitted file is empty.'] 776 800 777 >>> type(f.clean({'filename': 'name', 'content': 'Some File Content'}))801 >>> type(f.clean({'filename': 'name', 'content': 'Some File Content'})) 778 802 <class 'django.newforms.fields.UploadedFile'> 779 803 804 >>> unicode(f.clean({'filename': 'name', 'content': 'Some File Content'})) 805 u'name' 806 807 >>> type(f.clean({'filename': 'name', 'content': 'Some File Content'}, 'files/test4.pdf')) 808 <class 'django.newforms.fields.UploadedFile'> 809 780 810 # URLField ################################################################## 781 811 782 812 >>> f = URLField() … … 1105 1135 u'' 1106 1136 >>> f.clean(None) 1107 1137 u'' 1138 >>> f = ComboField(fields=[FileField(), CharField(max_length=20)]) 1139 >>> f.clean('data', 'some_file.txt') 1140 Traceback (most recent call last): 1141 ... 1142 ValidationError: [u'No file was submitted. Check the encoding type on the form.'] 1143 >>> f.clean('', 'some_file.txt') 1144 u'some_file.txt' 1145 >>> f.clean('', None) 1146 Traceback (most recent call last): 1147 ... 1148 ValidationError: [u'This field is required.'] 1149 >>> f.clean({'filename': 'filename.txt', 'content':'something'}) 1150 u'filename.txt' 1151 >>> f.clean({'filename': 'too_long_filename_for_this_combofield_here.txt', 'content':'something'}) 1152 Traceback (most recent call last): 1153 ... 1154 ValidationError: [u'Ensure this value has at most 20 characters (it has 46).'] 1108 1155 1156 # MultiValueField ########################################################## 1157 1158 >>> f = MultiValueField(fields=[FileField(), CharField(max_length=20)]) 1159 >>> f.clean([{'filename': 'some_file.txt', 'content':'something'}, 'Some text']) 1160 Traceback (most recent call last): 1161 ... 1162 NotImplementedError: Subclasses must implement this method. 1163 >>> f.clean([{'filename': 'some_file.txt', 'content':'something'}, 'alotoftext_more_than_20_chars']) 1164 Traceback (most recent call last): 1165 ... 1166 ValidationError: [u'Ensure this value has at most 20 characters (it has 29).'] 1167 >>> f.clean([None, None]) 1168 Traceback (most recent call last): 1169 ... 1170 ValidationError: [u'This field is required.'] 1171 >>> f.clean([None, 'Some text'], ['some_file.txt', None]) 1172 Traceback (most recent call last): 1173 ... 1174 NotImplementedError: Subclasses must implement this method. 1175 1109 1176 # SplitDateTimeField ########################################################## 1110 1177 1111 1178 >>> f = SplitDateTimeField()