#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.

Reply via email to