Commit 9883551d authored by Claude Paroz's avatar Claude Paroz
Browse files

Fixed #20039 -- Fixed has_changed form detection for required TypedChoiceFields

Thanks Florian Apolloner for the report and the review.
Also fixes #19643.
parent 6b483495
Loading
Loading
Loading
Loading
+8 −8
Original line number Diff line number Diff line
@@ -778,14 +778,15 @@ class ChoiceField(Field):

    def valid_value(self, value):
        "Check to see if the provided value is a valid choice"
        text_value = force_text(value)
        for k, v in self.choices:
            if isinstance(v, (list, tuple)):
                # This is an optgroup, so look inside the group for options
                for k2, v2 in v:
                    if value == smart_text(k2):
                    if value == k2 or text_value == force_text(k2):
                        return True
            else:
                if value == smart_text(k):
                if value == k or text_value == force_text(k):
                    return True
        return False

@@ -801,7 +802,6 @@ class TypedChoiceField(ChoiceField):
        right type.
        """
        value = super(TypedChoiceField, self).to_python(value)
        super(TypedChoiceField, self).validate(value)
        if value == self.empty_value or value in self.empty_values:
            return self.empty_value
        try:
@@ -810,9 +810,6 @@ class TypedChoiceField(ChoiceField):
            raise ValidationError(self.error_messages['invalid_choice'] % {'value': value})
        return value

    def validate(self, value):
        pass


class MultipleChoiceField(ChoiceField):
    hidden_widget = MultipleHiddenInput
@@ -864,7 +861,6 @@ class TypedMultipleChoiceField(MultipleChoiceField):
        right type.
        """
        value = super(TypedMultipleChoiceField, self).to_python(value)
        super(TypedMultipleChoiceField, self).validate(value)
        if value == self.empty_value or value in self.empty_values:
            return self.empty_value
        new_value = []
@@ -876,7 +872,11 @@ class TypedMultipleChoiceField(MultipleChoiceField):
        return new_value

    def validate(self, value):
        pass
        if value != self.empty_value:
            super(TypedMultipleChoiceField, self).validate(value)
        elif self.required:
            raise ValidationError(self.error_messages['required'])


class ComboField(Field):
    """
+10 −0
Original line number Diff line number Diff line
@@ -911,6 +911,11 @@ class FieldsTests(SimpleTestCase):
        f = TypedChoiceField(choices=[(1, "+1"), (-1, "-1")], coerce=int, required=False, empty_value=None)
        self.assertEqual(None, f.clean(''))

    def test_typedchoicefield_has_changed(self):
        # has_changed should not trigger required validation
        f = TypedChoiceField(choices=[(1, "+1"), (-1, "-1")], coerce=int, required=True)
        self.assertFalse(f._has_changed(None, ''))

    # NullBooleanField ############################################################

    def test_nullbooleanfield_1(self):
@@ -1060,6 +1065,11 @@ class FieldsTests(SimpleTestCase):
        f = TypedMultipleChoiceField(choices=[(1, "+1"), (-1, "-1")], coerce=int, required=False, empty_value=None)
        self.assertEqual(None, f.clean([]))

    def test_typedmultiplechoicefield_has_changed(self):
        # has_changed should not trigger required validation
        f = TypedMultipleChoiceField(choices=[(1, "+1"), (-1, "-1")], coerce=int, required=True)
        self.assertFalse(f._has_changed(None, ''))

   # ComboField ##################################################################

    def test_combofield_1(self):
+1 −1
Original line number Diff line number Diff line
@@ -61,10 +61,10 @@ class FormsRegressionsTestCase(TestCase):
        UNITS = ((b'\xd0\xbc\xd0\xb5\xd1\x81.', b'\xd0\xbc\xd0\xb5\xd1\x81.'),
                 (b'\xd1\x88\xd1\x82.', b'\xd1\x88\xd1\x82.'))
        f = ChoiceField(choices=UNITS)
        self.assertEqual(f.clean('\u0448\u0442.'), '\u0448\u0442.')
        with warnings.catch_warnings():
            # Ignore UnicodeWarning
            warnings.simplefilter("ignore")
            self.assertEqual(f.clean('\u0448\u0442.'), '\u0448\u0442.')
            self.assertEqual(f.clean(b'\xd1\x88\xd1\x82.'), '\u0448\u0442.')

        # Translated error messages used to be buggy.