1. from django import forms
    
  2. from django.core.exceptions import ValidationError
    
  3. from django.db import IntegrityError, models, transaction
    
  4. from django.test import SimpleTestCase, TestCase
    
  5. 
    
  6. from .models import BooleanModel, FksToBooleans, NullBooleanModel
    
  7. 
    
  8. 
    
  9. class BooleanFieldTests(TestCase):
    
  10.     def _test_get_prep_value(self, f):
    
  11.         self.assertIs(f.get_prep_value(True), True)
    
  12.         self.assertIs(f.get_prep_value("1"), True)
    
  13.         self.assertIs(f.get_prep_value(1), True)
    
  14.         self.assertIs(f.get_prep_value(False), False)
    
  15.         self.assertIs(f.get_prep_value("0"), False)
    
  16.         self.assertIs(f.get_prep_value(0), False)
    
  17.         self.assertIsNone(f.get_prep_value(None))
    
  18. 
    
  19.     def _test_to_python(self, f):
    
  20.         self.assertIs(f.to_python(1), True)
    
  21.         self.assertIs(f.to_python(0), False)
    
  22. 
    
  23.     def test_booleanfield_get_prep_value(self):
    
  24.         self._test_get_prep_value(models.BooleanField())
    
  25. 
    
  26.     def test_nullbooleanfield_get_prep_value(self):
    
  27.         self._test_get_prep_value(models.BooleanField(null=True))
    
  28. 
    
  29.     def test_booleanfield_to_python(self):
    
  30.         self._test_to_python(models.BooleanField())
    
  31. 
    
  32.     def test_nullbooleanfield_to_python(self):
    
  33.         self._test_to_python(models.BooleanField(null=True))
    
  34. 
    
  35.     def test_booleanfield_choices_blank(self):
    
  36.         """
    
  37.         BooleanField with choices and defaults doesn't generate a formfield
    
  38.         with the blank option (#9640, #10549).
    
  39.         """
    
  40.         choices = [(1, "Si"), (2, "No")]
    
  41.         f = models.BooleanField(choices=choices, default=1, null=False)
    
  42.         self.assertEqual(f.formfield().choices, choices)
    
  43. 
    
  44.     def test_booleanfield_choices_blank_desired(self):
    
  45.         """
    
  46.         BooleanField with choices and no default should generated a formfield
    
  47.         with the blank option.
    
  48.         """
    
  49.         choices = [(1, "Si"), (2, "No")]
    
  50.         f = models.BooleanField(choices=choices)
    
  51.         self.assertEqual(f.formfield().choices, [("", "---------")] + choices)
    
  52. 
    
  53.     def test_nullbooleanfield_formfield(self):
    
  54.         f = models.BooleanField(null=True)
    
  55.         self.assertIsInstance(f.formfield(), forms.NullBooleanField)
    
  56. 
    
  57.     def test_return_type(self):
    
  58.         b = BooleanModel.objects.create(bfield=True)
    
  59.         b.refresh_from_db()
    
  60.         self.assertIs(b.bfield, True)
    
  61. 
    
  62.         b2 = BooleanModel.objects.create(bfield=False)
    
  63.         b2.refresh_from_db()
    
  64.         self.assertIs(b2.bfield, False)
    
  65. 
    
  66.         b3 = NullBooleanModel.objects.create(nbfield=True)
    
  67.         b3.refresh_from_db()
    
  68.         self.assertIs(b3.nbfield, True)
    
  69. 
    
  70.         b4 = NullBooleanModel.objects.create(nbfield=False)
    
  71.         b4.refresh_from_db()
    
  72.         self.assertIs(b4.nbfield, False)
    
  73. 
    
  74.         # When an extra clause exists, the boolean conversions are applied with
    
  75.         # an offset (#13293).
    
  76.         b5 = BooleanModel.objects.extra(select={"string_col": "string"})[0]
    
  77.         self.assertNotIsInstance(b5.pk, bool)
    
  78. 
    
  79.     def test_select_related(self):
    
  80.         """
    
  81.         Boolean fields retrieved via select_related() should return booleans.
    
  82.         """
    
  83.         bmt = BooleanModel.objects.create(bfield=True)
    
  84.         bmf = BooleanModel.objects.create(bfield=False)
    
  85.         nbmt = NullBooleanModel.objects.create(nbfield=True)
    
  86.         nbmf = NullBooleanModel.objects.create(nbfield=False)
    
  87.         m1 = FksToBooleans.objects.create(bf=bmt, nbf=nbmt)
    
  88.         m2 = FksToBooleans.objects.create(bf=bmf, nbf=nbmf)
    
  89. 
    
  90.         # select_related('fk_field_name')
    
  91.         ma = FksToBooleans.objects.select_related("bf").get(pk=m1.id)
    
  92.         self.assertIs(ma.bf.bfield, True)
    
  93.         self.assertIs(ma.nbf.nbfield, True)
    
  94. 
    
  95.         # select_related()
    
  96.         mb = FksToBooleans.objects.select_related().get(pk=m1.id)
    
  97.         mc = FksToBooleans.objects.select_related().get(pk=m2.id)
    
  98.         self.assertIs(mb.bf.bfield, True)
    
  99.         self.assertIs(mb.nbf.nbfield, True)
    
  100.         self.assertIs(mc.bf.bfield, False)
    
  101.         self.assertIs(mc.nbf.nbfield, False)
    
  102. 
    
  103.     def test_null_default(self):
    
  104.         """
    
  105.         A BooleanField defaults to None, which isn't a valid value (#15124).
    
  106.         """
    
  107.         boolean_field = BooleanModel._meta.get_field("bfield")
    
  108.         self.assertFalse(boolean_field.has_default())
    
  109.         b = BooleanModel()
    
  110.         self.assertIsNone(b.bfield)
    
  111.         with transaction.atomic():
    
  112.             with self.assertRaises(IntegrityError):
    
  113.                 b.save()
    
  114. 
    
  115.         nb = NullBooleanModel()
    
  116.         self.assertIsNone(nb.nbfield)
    
  117.         nb.save()  # no error
    
  118. 
    
  119. 
    
  120. class ValidationTest(SimpleTestCase):
    
  121.     def test_boolean_field_doesnt_accept_empty_input(self):
    
  122.         f = models.BooleanField()
    
  123.         with self.assertRaises(ValidationError):
    
  124.             f.clean(None, None)
    
  125. 
    
  126.     def test_nullbooleanfield_blank(self):
    
  127.         """
    
  128.         NullBooleanField shouldn't throw a validation error when given a value
    
  129.         of None.
    
  130.         """
    
  131.         nullboolean = NullBooleanModel(nbfield=None)
    
  132.         nullboolean.full_clean()