#35449: SplitArrayField doesn't validate properly 
(django.contrib.postgres.forms)
--------------------------------------------+------------------------
               Reporter:  Matthijs          |          Owner:  (none)
                   Type:  Bug               |         Status:  new
              Component:  contrib.postgres  |        Version:  4.2
               Severity:  Normal            |       Keywords:
           Triage Stage:  Unreviewed        |      Has patch:  0
    Needs documentation:  0                 |    Needs tests:  0
Patch needs improvement:  0                 |  Easy pickings:  0
                  UI/UX:  0                 |
--------------------------------------------+------------------------
 I created an {{{ArrayField(models.CharField(), size=3)}}} on one of my
 models and created a form for it using the {{{SplitArrayField}}}. My
 requirements where that the array field was optional to fill in and that
 you could also just fill in one of the CharFields and leave the others
 blank. So according to
 
[https://docs.djangoproject.com/en/4.2/ref/contrib/postgres/forms/#django.contrib.postgres.forms.SplitArrayField.remove_trailing_nulls
 the docs] I was to set the {{{CharField}}} in my {{{SplitArrayField}}} to
 {{{required=True}}} and {{{remove_trailing_nulls=True}}} on the
 {{{SplitArrayField}}}.
 {{{
 SplitArrayField(
     forms.CharField(required=True, max_length=148),
     size=3,
     widget=SplitArrayWidget(forms.TextInput(attrs={'size': '148'}), 3),
     remove_trailing_nulls=True,
     required=False
 )
 }}}

 To my surprise the form did not validate properly and I was able to submit
 inputs that exceeded the {{{max_length}}} specified in my form.
 Looking at the {{{def clean}}} method of the {{{SplitArrayField}}} I
 suspect a problem there.

 {{{
 try:
     cleaned_data.append(self.base_field.clean(item))
 except ValidationError as error:
     errors.append(
         prefix_validation_error(
             error,
             self.error_messages["item_invalid"],
             code="item_invalid",
             params={"nth": index + 1},
         )
     )
     cleaned_data.append(None)
     ...
 }}}

 If there is any {{{ValidationError}}} the error is added to {{{errors}}},
 at the same time {{{None}}} is appended to the {{{cleaned_data}}}.
 This causes issues with the {{{self._remove_trailing_nulls}}} later on.

 {{{
 cleaned_data, null_index = self._remove_trailing_nulls(cleaned_data)
 if null_index is not None:
     errors = errors[:null_index]
 errors = list(filter(None, errors))
 }}}

 {{{cleaned_data}}} is passed to {{{self._remove_trailing_nulls}}} and
 because {{{remove_trailing_nulls=True}}}, {{{null_index}}} will be {{{0}}}
 thus {{{errors}}} is reassigned to an empty list.

 I wrote a test case showcasing this issue:
 {{{
 from django import forms
 from django.contrib.postgres.forms import SplitArrayField

 class TestForm1(forms.Form):
     field = SplitArrayField(
         forms.CharField(max_length=5, required=True),
         size=3,
         remove_trailing_nulls=True,
         required=False,
     )

 class TestForm2(forms.Form):
     field = forms.CharField(max_length=5, required=True)

 class SplitArrayFieldTest(TestCase):
     def test_validation_error(self):
         invalid_value = 'invalid'
         form1 = TestForm1(data={'field': [invalid_value, '', '']})
         form2 = TestForm2(data={'field': invalid_value})

         self.assertFalse(form1.is_valid())  #is_valid() should return
 False, but returns True
         self.assertFalse(form2.is_valid())
 }}}
-- 
Ticket URL: <https://code.djangoproject.com/ticket/35449>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-updates+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/0107018f761633b8-991d65c0-9681-45fe-a680-2242704c8bc6-000000%40eu-central-1.amazonses.com.

Reply via email to