Ticket #6405: combofield_multivaluefield_pass_initial_trough.2.diff
File combofield_multivaluefield_pass_initial_trough.2.diff, 9.3 KB (added by , 16 years ago) |
---|
-
django/forms/fields.py
diff --git a/django/forms/fields.py b/django/forms/fields.py index ccb54d8..5da3a01 100644
a b except ImportError: 439 439 # It's OK if Django settings aren't configured. 440 440 URL_VALIDATOR_USER_AGENT = 'Django (http://www.djangoproject.com/)' 441 441 442 443 class FileField(Field): 442 class FieldWithInitial(object): 443 pass 444 445 class FileField(Field, FieldWithInitial): 444 446 widget = FileInput 445 447 default_error_messages = { 446 448 'invalid': _(u"No file was submitted. Check the encoding type on the form."), … … class FileField(Field): 454 456 def clean(self, data, initial=None): 455 457 super(FileField, self).clean(initial or data) 456 458 if not self.required and data in EMPTY_VALUES: 457 return None459 return initial or None 458 460 elif not data and initial: 459 461 return initial 460 462 … … class MultipleChoiceField(ChoiceField): 714 716 raise ValidationError(self.error_messages['invalid_choice'] % {'value': val}) 715 717 return new_value 716 718 717 class ComboField(Field ):719 class ComboField(Field, FieldWithInitial): 718 720 """ 719 721 A Field whose clean() method calls multiple Field clean() methods. 720 722 """ … … class ComboField(Field): 727 729 f.required = False 728 730 self.fields = fields 729 731 730 def clean(self, value ):732 def clean(self, value, initial=None): 731 733 """ 732 734 Validates the given value against all of self.fields, which is a 733 735 list of Field instances. 734 736 """ 735 super(ComboField, self).clean( value)737 super(ComboField, self).clean(initial or value) 736 738 for field in self.fields: 737 value = field.clean(value) 739 if isinstance(field, FieldWithInitial): 740 value = field.clean(value, initial) 741 else: 742 value = field.clean(value) 738 743 return value 739 744 740 class MultiValueField(Field ):745 class MultiValueField(Field, FieldWithInitial): 741 746 """ 742 747 A Field that aggregates the logic of multiple Fields. 743 748 … … class MultiValueField(Field): 767 772 f.required = False 768 773 self.fields = fields 769 774 770 def clean(self, value ):775 def clean(self, value, initial=None): 771 776 """ 772 777 Validates every value in the given list. A value is validated against 773 778 the corresponding Field in self.fields. … … class MultiValueField(Field): 776 781 fields=(DateField(), TimeField()), clean() would call 777 782 DateField.clean(value[0]) and TimeField.clean(value[1]). 778 783 """ 779 clean_data = [] 784 clean_data, value_list, initial_list, takes_initial_list = [], [], [], [] 785 value, initial = value or [], initial or [] 780 786 errors = ErrorList() 781 787 if not value or isinstance(value, (list, tuple)): 782 if not value or not [v for v in value if v not in EMPTY_VALUES]: 788 for i, field in enumerate(self.fields): 789 try: 790 field_value = value[i] 791 except IndexError: 792 field_value = None 793 value_list.append(field_value) 794 try: 795 field_initial = initial[i] 796 except IndexError: 797 field_initial = None 798 initial_list.append(field_initial) 799 takes_initial_list.append(isinstance(field, FieldWithInitial)) 800 801 if not value or not [(v, i, t) for v, i, t in \ 802 zip(value_list, initial_list, takes_initial_list) \ 803 if v not in EMPTY_VALUES or t and i not in EMPTY_VALUES]: 804 783 805 if self.required: 784 806 raise ValidationError(self.error_messages['required']) 785 807 else: … … class MultiValueField(Field): 787 809 else: 788 810 raise ValidationError(self.error_messages['invalid']) 789 811 for i, field in enumerate(self.fields): 812 field_value = value_list[i] 813 field_initial = initial_list[i] 814 takes_initial = takes_initial_list[i] 815 if self.required and not ( (takes_initial and field_initial not in EMPTY_VALUES) or 816 (field_value not in EMPTY_VALUES) ): 817 raise ValidationError(self.error_messages['required']) 790 818 try: 791 field_value = value[i] 792 except IndexError: 793 field_value = None 794 if self.required and field_value in EMPTY_VALUES: 795 raise ValidationError(self.error_messages['required']) 796 try: 797 clean_data.append(field.clean(field_value)) 819 if takes_initial: 820 clean_data.append(field.clean(field_value, field_initial)) 821 else: 822 clean_data.append(field.clean(field_value)) 798 823 except ValidationError, e: 799 824 # Collect all validation errors in a single list, which we'll 800 825 # raise at the end of clean(), rather than raising a single … … class MultiValueField(Field): 802 827 errors.extend(e.messages) 803 828 if errors: 804 829 raise ValidationError(errors) 805 return self.compress(clean_data )830 return self.compress(clean_data, initial_list) 806 831 807 def compress(self, data_list ):832 def compress(self, data_list, initial_list=[]): 808 833 """ 809 834 Returns a single value for the given list of values. The values can be 810 835 assumed to be valid. … … class SplitDateTimeField(MultiValueField): 860 885 ) 861 886 super(SplitDateTimeField, self).__init__(fields, *args, **kwargs) 862 887 863 def compress(self, data_list ):888 def compress(self, data_list, initial_list=[]): 864 889 if data_list: 865 890 # Raise a validation error if time or date is empty 866 891 # (possible if SplitDateTimeField has required=False). -
django/forms/forms.py
diff --git a/django/forms/forms.py b/django/forms/forms.py index f5bea10..45c1de7 100644
a b from django.utils.html import conditional_escape 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 Media, media_property, TextInput, Textarea 14 14 from util import flatatt, ErrorDict, ErrorList, ValidationError 15 15 … … class BaseForm(StrAndUnicode): 224 224 # widgets split data over several HTML fields. 225 225 value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name)) 226 226 try: 227 if isinstance(field, Fi leField):227 if isinstance(field, FieldWithInitial): 228 228 initial = self.initial.get(name, field.initial) 229 229 value = field.clean(value, initial) 230 230 else: -
tests/regressiontests/forms/extra.py
diff --git a/tests/regressiontests/forms/extra.py b/tests/regressiontests/forms/extra.py index 80f7ef6..5ba45b2 100644
a b True 276 276 ... ) 277 277 ... super(ComplexField, self).__init__(fields, required, widget, label, initial) 278 278 ... 279 ... def compress(self, data_list ):279 ... def compress(self, data_list, initial_list=[]): 280 280 ... if data_list: 281 281 ... return '%s,%s,%s' % (data_list[0],''.join(data_list[1]),data_list[2]) 282 282 ... return None -
tests/regressiontests/forms/fields.py
diff --git a/tests/regressiontests/forms/fields.py b/tests/regressiontests/forms/fields.py index fa5a62a..eabded7 100644
a b ValidationError: [u'Enter a valid e-mail address.'] 1290 1290 u'' 1291 1291 >>> f.clean(None) 1292 1292 u'' 1293 >>> f = ComboField(fields=[FileField(), CharField(max_length=20)]) 1294 >>> f.clean('data', 'some_file.txt') 1295 Traceback (most recent call last): 1296 ... 1297 ValidationError: [u'No file was submitted. Check the encoding type on the form.'] 1298 >>> f.clean('', 'some_file.txt') 1299 u'some_file.txt' 1300 >>> f.clean('', None) 1301 Traceback (most recent call last): 1302 ... 1303 ValidationError: [u'This field is required.'] 1304 >>> f.clean({'filename': 'filename.txt', 'content':'something'}) 1305 u'filename.txt' 1306 >>> f.clean({'filename': 'too_long_filename_for_this_combofield_here.txt', 'content':'something'}) 1307 Traceback (most recent call last): 1308 ... 1309 ValidationError: [u'Ensure this value has at most 20 characters (it has 46).'] 1310 1311 # MultiValueField ########################################################## 1312 1313 >>> f = MultiValueField(fields=[FileField(), CharField(max_length=20)]) 1314 >>> f.clean([{'filename': 'some_file.txt', 'content':'something'}, 'Some text']) 1315 Traceback (most recent call last): 1316 ... 1317 NotImplementedError: Subclasses must implement this method. 1318 >>> f.clean([{'filename': 'some_file.txt', 'content':'something'}, 'alotoftext_more_than_20_chars']) 1319 Traceback (most recent call last): 1320 ... 1321 ValidationError: [u'Ensure this value has at most 20 characters (it has 29).'] 1322 >>> f.clean([None, None]) 1323 Traceback (most recent call last): 1324 ... 1325 ValidationError: [u'This field is required.'] 1326 >>> f.clean([None, 'Some text'], ['some_file.txt', None]) 1327 Traceback (most recent call last): 1328 ... 1329 NotImplementedError: Subclasses must implement this method. 1293 1330 1294 1331 # FilePathField ############################################################### 1295 1332