Skip to content

Commit fb453ba

Browse files
committed
Explicitly handle component classes with a bool class attribute and a form_class with a BooleanField so the frontend context variable is correct.
1 parent c05a9b5 commit fb453ba

File tree

3 files changed

+26
-0
lines changed

3 files changed

+26
-0
lines changed

django_unicorn/components/unicorn_view.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from django.core.cache import caches
1010
from django.core.exceptions import ImproperlyConfigured
1111
from django.db.models import Model
12+
from django.forms.widgets import CheckboxInput
1213
from django.http import HttpRequest
1314
from django.utils.decorators import classonlymethod
1415
from django.views.generic.base import TemplateView
@@ -400,6 +401,12 @@ def get_frontend_context_variables(self) -> str:
400401
cleaned_value = form.cleaned_data[key]
401402
value = field.widget.format_value(cleaned_value)
402403

404+
if isinstance(field.widget, CheckboxInput) and isinstance(
405+
cleaned_value, bool
406+
):
407+
# Handle booleans for checkboxes explicitly because `format_value` returns `None` in this case
408+
value = cleaned_value
409+
403410
# Don't update the frontend variable if the only change is
404411
# stripping off the whitespace from the field value
405412
# https://docs.djangoproject.com/en/stable/ref/forms/fields/#django.forms.CharField.strip

tests/components/test_component.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from django_unicorn.components import UnicornView
77
from django_unicorn.serializer import InvalidFieldNameError
8+
from tests.views.fake_components import FakeValidationComponent
89

910

1011
class ExampleComponent(UnicornView):
@@ -236,3 +237,19 @@ class Meta:
236237
component = TestComponent(component_id="asdf1234", component_name="hello-world")
237238
assert "name" not in component.get_frontend_context_variables()
238239
assert "name" not in component.get_context_data()
240+
241+
242+
def test_get_frontend_context_variables_form_with_boolean_field(component):
243+
"""
244+
Form classes with BooleanField and CheckboxInput widget set the bool values to `None`
245+
without an explicit fix.
246+
"""
247+
248+
component = FakeValidationComponent(
249+
component_id="asdf1234", component_name="example"
250+
)
251+
252+
frontend_context_variables = component.get_frontend_context_variables()
253+
frontend_context_variables_dict = orjson.loads(frontend_context_variables)
254+
255+
assert frontend_context_variables_dict.get("permanent")

tests/views/fake_components.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ class FakeValidationForm(forms.Form):
6161
text = forms.CharField(min_length=3, max_length=10)
6262
date_time = forms.DateTimeField()
6363
number = forms.IntegerField()
64+
permanent = forms.BooleanField()
6465

6566

6667
class FakeValidationComponent(UnicornView):
@@ -70,6 +71,7 @@ class FakeValidationComponent(UnicornView):
7071
text = "hello"
7172
number = ""
7273
date_time = datetime(2020, 9, 13, 17, 45, 14)
74+
permanent = True
7375

7476
def set_text_no_validation(self):
7577
self.text = "no validation"

0 commit comments

Comments
 (0)