#35126: forms.NullBooleanField's validation logic is surprising
------------------------------+--------------------------------------
Reporter: Jeremy Lainé | Owner: nobody
Type: Bug | Status: new
Component: Forms | Version: 5.0
Severity: Normal | Resolution:
Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
------------------------------+--------------------------------------
Description changed by Jeremy Lainé:
Old description:
> Reading NullBooleanField's code lead me to believe that it would clean
> `"1"` to `True`, and `"0"` to `False`", just like `BooleanField` does:
>
> https://github.com/django/django/blob/10c7c7320baf1c655fcb91202169d77725c9c4bd/django/forms/fields.py#L850
>
> A simple field-level test works:
>
> {{{
> >>> from django import forms
> >>> field = forms.NullBooleanField()
> >>> field.clean("1")
> True
> >>> field.clean("0")
> False
> }}}
>
> But using this in an actual form fails, not the difference between the
> `BooleanField` and `NullBooleanField`:
>
> {{{
> >>> class DemoForm(forms.Form):
> ... field_a = forms.BooleanField()
> ... field_b = forms.NullBooleanField()
> ...
> >>> form = DemoForm({"field_a": "1", "field_b": "1"})
> >>> form.is_valid()
> >>> form.cleaned_data
> {'field_a': True, 'field_b': None}
> }}}
>
> The problem is that by default `NullBooleanField` uses a
> `NullBooleanSelect` which mangles the submitted data for some obscure
> backwards-compatibility reason:
>
> https://github.com/django/django/blob/10c7c7320baf1c655fcb91202169d77725c9c4bd/django/forms/widgets.py#L816
New description:
Reading NullBooleanField's code lead me to believe that it would clean
`"1"` to `True`, and `"0"` to `False`", just like `BooleanField` does:
https://github.com/django/django/blob/10c7c7320baf1c655fcb91202169d77725c9c4bd/django/forms/fields.py#L850
A simple field-level test works:
{{{
>>> from django import forms
>>> field = forms.NullBooleanField()
>>> field.clean("1")
True
>>> field.clean("0")
False
}}}
But using this in an actual form fails, note the difference between the
`BooleanField` and `NullBooleanField`:
{{{
>>> class DemoForm(forms.Form):
... field_a = forms.BooleanField()
... field_b = forms.NullBooleanField()
...
>>> form = DemoForm({"field_a": "1", "field_b": "1"})
>>> form.is_valid()
>>> form.cleaned_data
{'field_a': True, 'field_b': None}
}}}
The problem is that by default `NullBooleanField` uses a
`NullBooleanSelect` which mangles the submitted data for some obscure
backwards-compatibility reason:
https://github.com/django/django/blob/10c7c7320baf1c655fcb91202169d77725c9c4bd/django/forms/widgets.py#L816
--
--
Ticket URL: <https://code.djangoproject.com/ticket/35126#comment:1>
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 [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/0107018d1d15e166-290ce659-0153-44d4-b39c-82467f3dd1d1-000000%40eu-central-1.amazonses.com.