Ticket #6405: combofield_multivaluefield_pass_initial_trough.diff
File combofield_multivaluefield_pass_initial_trough.diff, 9.2 KB (added by , 17 years ago) |
---|
-
django/newforms/fields.py
413 413 # It's OK if Django settings aren't configured. 414 414 URL_VALIDATOR_USER_AGENT = 'Django (http://www.djangoproject.com/)' 415 415 416 class FieldWithInitial(object): 417 pass 418 416 419 class UploadedFile(StrAndUnicode): 417 420 "A wrapper for files uploaded in a FileField" 418 421 def __init__(self, filename, content): … … 426 429 """ 427 430 return self.filename 428 431 429 class FileField(Field ):432 class FileField(Field, FieldWithInitial): 430 433 widget = FileInput 431 434 default_error_messages = { 432 435 'invalid': _(u"No file was submitted. Check the encoding type on the form."), … … 440 443 def clean(self, data, initial=None): 441 444 super(FileField, self).clean(initial or data) 442 445 if not self.required and data in EMPTY_VALUES: 443 return None446 return initial or None 444 447 elif not data and initial: 445 448 return initial 446 449 try: … … 615 618 raise ValidationError(self.error_messages['invalid_choice'] % {'value': val}) 616 619 return new_value 617 620 618 class ComboField(Field ):621 class ComboField(Field, FieldWithInitial): 619 622 """ 620 623 A Field whose clean() method calls multiple Field clean() methods. 621 624 """ … … 628 631 f.required = False 629 632 self.fields = fields 630 633 631 def clean(self, value ):634 def clean(self, value, initial=None): 632 635 """ 633 636 Validates the given value against all of self.fields, which is a 634 637 list of Field instances. 635 638 """ 636 super(ComboField, self).clean( value)639 super(ComboField, self).clean(initial or value) 637 640 for field in self.fields: 638 value = field.clean(value) 641 if isinstance(field, FieldWithInitial): 642 value = field.clean(value, initial) 643 else: 644 value = field.clean(value) 639 645 return value 640 646 641 class MultiValueField(Field ):647 class MultiValueField(Field, FieldWithInitial): 642 648 """ 643 649 A Field that aggregates the logic of multiple Fields. 644 650 … … 668 674 f.required = False 669 675 self.fields = fields 670 676 671 def clean(self, value ):677 def clean(self, value, initial=None): 672 678 """ 673 679 Validates every value in the given list. A value is validated against 674 680 the corresponding Field in self.fields. … … 677 683 fields=(DateField(), TimeField()), clean() would call 678 684 DateField.clean(value[0]) and TimeField.clean(value[1]). 679 685 """ 680 clean_data = [] 686 clean_data, value_list, initial_list, takes_initial_list = [], [], [], [] 687 value, initial = value or [], initial or [] 681 688 errors = ErrorList() 682 689 if not value or isinstance(value, (list, tuple)): 683 if not value or not [v for v in value if v not in EMPTY_VALUES]: 690 for i, field in enumerate(self.fields): 691 try: 692 field_value = value[i] 693 except IndexError: 694 field_value = None 695 value_list.append(field_value) 696 try: 697 field_initial = initial[i] 698 except IndexError: 699 field_initial = None 700 initial_list.append(field_initial) 701 takes_initial_list.append(isinstance(field, FieldWithInitial)) 702 703 if not value or not [(v, i, t) for v, i, t in \ 704 zip(value_list, initial_list, takes_initial_list) \ 705 if v not in EMPTY_VALUES or t and i not in EMPTY_VALUES]: 706 684 707 if self.required: 685 708 raise ValidationError(self.error_messages['required']) 686 709 else: … … 688 711 else: 689 712 raise ValidationError(self.error_messages['invalid']) 690 713 for i, field in enumerate(self.fields): 714 field_value = value_list[i] 715 field_initial = initial_list[i] 716 takes_initial = takes_initial_list[i] 717 if self.required and not ( (takes_initial and field_initial not in EMPTY_VALUES) or 718 (field_value not in EMPTY_VALUES) ): 719 raise ValidationError(self.error_messages['required']) 691 720 try: 692 field_value = value[i] 693 except IndexError: 694 field_value = None 695 if self.required and field_value in EMPTY_VALUES: 696 raise ValidationError(self.error_messages['required']) 697 try: 698 clean_data.append(field.clean(field_value)) 721 if takes_initial: 722 clean_data.append(field.clean(field_value, field_initial)) 723 else: 724 clean_data.append(field.clean(field_value)) 699 725 except ValidationError, e: 700 726 # Collect all validation errors in a single list, which we'll 701 727 # raise at the end of clean(), rather than raising a single … … 703 729 errors.extend(e.messages) 704 730 if errors: 705 731 raise ValidationError(errors) 706 return self.compress(clean_data )732 return self.compress(clean_data, initial_list) 707 733 708 def compress(self, data_list ):734 def compress(self, data_list, initial_list=[]): 709 735 """ 710 736 Returns a single value for the given list of values. The values can be 711 737 assumed to be valid. … … 732 758 ) 733 759 super(SplitDateTimeField, self).__init__(fields, *args, **kwargs) 734 760 735 def compress(self, data_list ):761 def compress(self, data_list, initial_list=[]): 736 762 if data_list: 737 763 # Raise a validation error if time or date is empty 738 764 # (possible if SplitDateTimeField has required=False). -
django/newforms/forms.py
9 9 from django.utils.encoding import StrAndUnicode, smart_unicode, force_unicode 10 10 from django.utils.safestring import mark_safe 11 11 12 from fields import Field, Fi leField12 from fields import Field, FieldWithInitial 13 13 from widgets import TextInput, Textarea 14 14 from util import flatatt, ErrorDict, ErrorList, ValidationError 15 15 … … 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 if isinstance(field, Fi leField):185 if isinstance(field, FieldWithInitial): 186 186 initial = self.initial.get(name, field.initial) 187 187 value = field.clean(value, initial) 188 188 else: -
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
1132 1132 u'' 1133 1133 >>> f.clean(None) 1134 1134 u'' 1135 >>> f = ComboField(fields=[FileField(), CharField(max_length=20)]) 1136 >>> f.clean('data', 'some_file.txt') 1137 Traceback (most recent call last): 1138 ... 1139 ValidationError: [u'No file was submitted. Check the encoding type on the form.'] 1140 >>> f.clean('', 'some_file.txt') 1141 u'some_file.txt' 1142 >>> f.clean('', None) 1143 Traceback (most recent call last): 1144 ... 1145 ValidationError: [u'This field is required.'] 1146 >>> f.clean({'filename': 'filename.txt', 'content':'something'}) 1147 u'filename.txt' 1148 >>> f.clean({'filename': 'too_long_filename_for_this_combofield_here.txt', 'content':'something'}) 1149 Traceback (most recent call last): 1150 ... 1151 ValidationError: [u'Ensure this value has at most 20 characters (it has 46).'] 1135 1152 1153 # MultiValueField ########################################################## 1154 1155 >>> f = MultiValueField(fields=[FileField(), CharField(max_length=20)]) 1156 >>> f.clean([{'filename': 'some_file.txt', 'content':'something'}, 'Some text']) 1157 Traceback (most recent call last): 1158 ... 1159 NotImplementedError: Subclasses must implement this method. 1160 >>> f.clean([{'filename': 'some_file.txt', 'content':'something'}, 'alotoftext_more_than_20_chars']) 1161 Traceback (most recent call last): 1162 ... 1163 ValidationError: [u'Ensure this value has at most 20 characters (it has 29).'] 1164 >>> f.clean([None, None]) 1165 Traceback (most recent call last): 1166 ... 1167 ValidationError: [u'This field is required.'] 1168 >>> f.clean([None, 'Some text'], ['some_file.txt', None]) 1169 Traceback (most recent call last): 1170 ... 1171 NotImplementedError: Subclasses must implement this method. 1172 1136 1173 # SplitDateTimeField ########################################################## 1137 1174 1138 1175 >>> f = SplitDateTimeField()