test_nullbooleanfield.py 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. from django.forms import Form, HiddenInput, NullBooleanField, RadioSelect
  2. from django.test import SimpleTestCase
  3. from . import FormFieldAssertionsMixin
  4. class NullBooleanFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
  5. def test_nullbooleanfield_clean(self):
  6. f = NullBooleanField()
  7. self.assertIsNone(f.clean(''))
  8. self.assertTrue(f.clean(True))
  9. self.assertFalse(f.clean(False))
  10. self.assertIsNone(f.clean(None))
  11. self.assertFalse(f.clean('0'))
  12. self.assertTrue(f.clean('1'))
  13. self.assertIsNone(f.clean('2'))
  14. self.assertIsNone(f.clean('3'))
  15. self.assertIsNone(f.clean('hello'))
  16. self.assertTrue(f.clean('true'))
  17. self.assertFalse(f.clean('false'))
  18. def test_nullbooleanfield_2(self):
  19. # The internal value is preserved if using HiddenInput (#7753).
  20. class HiddenNullBooleanForm(Form):
  21. hidden_nullbool1 = NullBooleanField(widget=HiddenInput, initial=True)
  22. hidden_nullbool2 = NullBooleanField(widget=HiddenInput, initial=False)
  23. f = HiddenNullBooleanForm()
  24. self.assertHTMLEqual(
  25. '<input type="hidden" name="hidden_nullbool1" value="True" id="id_hidden_nullbool1">'
  26. '<input type="hidden" name="hidden_nullbool2" value="False" id="id_hidden_nullbool2">',
  27. str(f)
  28. )
  29. def test_nullbooleanfield_3(self):
  30. class HiddenNullBooleanForm(Form):
  31. hidden_nullbool1 = NullBooleanField(widget=HiddenInput, initial=True)
  32. hidden_nullbool2 = NullBooleanField(widget=HiddenInput, initial=False)
  33. f = HiddenNullBooleanForm({'hidden_nullbool1': 'True', 'hidden_nullbool2': 'False'})
  34. self.assertIsNone(f.full_clean())
  35. self.assertTrue(f.cleaned_data['hidden_nullbool1'])
  36. self.assertFalse(f.cleaned_data['hidden_nullbool2'])
  37. def test_nullbooleanfield_4(self):
  38. # Make sure we're compatible with MySQL, which uses 0 and 1 for its
  39. # boolean values (#9609).
  40. NULLBOOL_CHOICES = (('1', 'Yes'), ('0', 'No'), ('', 'Unknown'))
  41. class MySQLNullBooleanForm(Form):
  42. nullbool0 = NullBooleanField(widget=RadioSelect(choices=NULLBOOL_CHOICES))
  43. nullbool1 = NullBooleanField(widget=RadioSelect(choices=NULLBOOL_CHOICES))
  44. nullbool2 = NullBooleanField(widget=RadioSelect(choices=NULLBOOL_CHOICES))
  45. f = MySQLNullBooleanForm({'nullbool0': '1', 'nullbool1': '0', 'nullbool2': ''})
  46. self.assertIsNone(f.full_clean())
  47. self.assertTrue(f.cleaned_data['nullbool0'])
  48. self.assertFalse(f.cleaned_data['nullbool1'])
  49. self.assertIsNone(f.cleaned_data['nullbool2'])
  50. def test_nullbooleanfield_changed(self):
  51. f = NullBooleanField()
  52. self.assertTrue(f.has_changed(False, None))
  53. self.assertTrue(f.has_changed(None, False))
  54. self.assertFalse(f.has_changed(None, None))
  55. self.assertFalse(f.has_changed(False, False))
  56. self.assertTrue(f.has_changed(True, False))
  57. self.assertTrue(f.has_changed(True, None))
  58. self.assertTrue(f.has_changed(True, False))
  59. # HiddenInput widget sends string values for boolean but doesn't clean them in value_from_datadict
  60. self.assertFalse(f.has_changed(False, 'False'))
  61. self.assertFalse(f.has_changed(True, 'True'))
  62. self.assertFalse(f.has_changed(None, ''))
  63. self.assertTrue(f.has_changed(False, 'True'))
  64. self.assertTrue(f.has_changed(True, 'False'))
  65. self.assertTrue(f.has_changed(None, 'False'))