2016-12-20 07:47:30 +08:00
|
|
|
from django import forms
|
2016-03-22 09:06:54 +08:00
|
|
|
from django.core.exceptions import ValidationError
|
2016-04-24 01:13:31 +08:00
|
|
|
from django.db import IntegrityError, models, transaction
|
2016-03-22 09:06:54 +08:00
|
|
|
from django.test import SimpleTestCase, TestCase
|
|
|
|
|
|
|
|
from .models import BooleanModel, FksToBooleans, NullBooleanModel
|
|
|
|
|
|
|
|
|
|
|
|
class BooleanFieldTests(TestCase):
|
2016-04-24 01:13:31 +08:00
|
|
|
def _test_get_prep_value(self, f):
|
2016-06-17 02:19:18 +08:00
|
|
|
self.assertIs(f.get_prep_value(True), True)
|
|
|
|
self.assertIs(f.get_prep_value("1"), True)
|
|
|
|
self.assertIs(f.get_prep_value(1), True)
|
|
|
|
self.assertIs(f.get_prep_value(False), False)
|
|
|
|
self.assertIs(f.get_prep_value("0"), False)
|
|
|
|
self.assertIs(f.get_prep_value(0), False)
|
|
|
|
self.assertIsNone(f.get_prep_value(None))
|
2016-03-22 09:06:54 +08:00
|
|
|
|
|
|
|
def _test_to_python(self, f):
|
|
|
|
self.assertIs(f.to_python(1), True)
|
|
|
|
self.assertIs(f.to_python(0), False)
|
|
|
|
|
2016-04-24 01:13:31 +08:00
|
|
|
def test_booleanfield_get_prep_value(self):
|
|
|
|
self._test_get_prep_value(models.BooleanField())
|
2016-03-22 09:06:54 +08:00
|
|
|
|
2016-04-24 01:13:31 +08:00
|
|
|
def test_nullbooleanfield_get_prep_value(self):
|
2017-05-06 22:56:28 +08:00
|
|
|
self._test_get_prep_value(models.BooleanField(null=True))
|
|
|
|
|
2016-03-22 09:06:54 +08:00
|
|
|
def test_booleanfield_to_python(self):
|
|
|
|
self._test_to_python(models.BooleanField())
|
|
|
|
|
|
|
|
def test_nullbooleanfield_to_python(self):
|
2017-05-06 22:56:28 +08:00
|
|
|
self._test_to_python(models.BooleanField(null=True))
|
|
|
|
|
2016-03-22 09:06:54 +08:00
|
|
|
def test_booleanfield_choices_blank(self):
|
|
|
|
"""
|
|
|
|
BooleanField with choices and defaults doesn't generate a formfield
|
|
|
|
with the blank option (#9640, #10549).
|
|
|
|
"""
|
|
|
|
choices = [(1, "Si"), (2, "No")]
|
|
|
|
f = models.BooleanField(choices=choices, default=1, null=False)
|
|
|
|
self.assertEqual(f.formfield().choices, choices)
|
|
|
|
|
2020-09-09 18:26:34 +08:00
|
|
|
def test_booleanfield_choices_blank_desired(self):
|
|
|
|
"""
|
|
|
|
BooleanField with choices and no default should generated a formfield
|
|
|
|
with the blank option.
|
|
|
|
"""
|
|
|
|
choices = [(1, "Si"), (2, "No")]
|
|
|
|
f = models.BooleanField(choices=choices)
|
|
|
|
self.assertEqual(f.formfield().choices, [("", "---------")] + choices)
|
|
|
|
|
2016-12-20 07:47:30 +08:00
|
|
|
def test_nullbooleanfield_formfield(self):
|
2017-05-06 22:56:28 +08:00
|
|
|
f = models.BooleanField(null=True)
|
|
|
|
self.assertIsInstance(f.formfield(), forms.NullBooleanField)
|
2016-12-20 07:47:30 +08:00
|
|
|
|
2016-03-22 09:06:54 +08:00
|
|
|
def test_return_type(self):
|
|
|
|
b = BooleanModel.objects.create(bfield=True)
|
|
|
|
b.refresh_from_db()
|
2016-06-17 02:19:18 +08:00
|
|
|
self.assertIs(b.bfield, True)
|
2016-03-22 09:06:54 +08:00
|
|
|
|
|
|
|
b2 = BooleanModel.objects.create(bfield=False)
|
|
|
|
b2.refresh_from_db()
|
2016-06-17 02:19:18 +08:00
|
|
|
self.assertIs(b2.bfield, False)
|
2016-03-22 09:06:54 +08:00
|
|
|
|
2021-01-14 04:28:09 +08:00
|
|
|
b3 = NullBooleanModel.objects.create(nbfield=True)
|
2016-03-22 09:06:54 +08:00
|
|
|
b3.refresh_from_db()
|
2016-06-17 02:19:18 +08:00
|
|
|
self.assertIs(b3.nbfield, True)
|
2016-03-22 09:06:54 +08:00
|
|
|
|
2021-01-14 04:28:09 +08:00
|
|
|
b4 = NullBooleanModel.objects.create(nbfield=False)
|
2016-03-22 09:06:54 +08:00
|
|
|
b4.refresh_from_db()
|
2016-06-17 02:19:18 +08:00
|
|
|
self.assertIs(b4.nbfield, False)
|
2016-03-22 09:06:54 +08:00
|
|
|
|
|
|
|
# When an extra clause exists, the boolean conversions are applied with
|
|
|
|
# an offset (#13293).
|
2022-02-22 17:29:38 +08:00
|
|
|
b5 = BooleanModel.objects.extra(select={"string_col": "string"})[0]
|
2016-03-22 09:06:54 +08:00
|
|
|
self.assertNotIsInstance(b5.pk, bool)
|
|
|
|
|
|
|
|
def test_select_related(self):
|
|
|
|
"""
|
|
|
|
Boolean fields retrieved via select_related() should return booleans.
|
|
|
|
"""
|
|
|
|
bmt = BooleanModel.objects.create(bfield=True)
|
|
|
|
bmf = BooleanModel.objects.create(bfield=False)
|
2021-01-14 04:28:09 +08:00
|
|
|
nbmt = NullBooleanModel.objects.create(nbfield=True)
|
|
|
|
nbmf = NullBooleanModel.objects.create(nbfield=False)
|
2016-03-22 09:06:54 +08:00
|
|
|
m1 = FksToBooleans.objects.create(bf=bmt, nbf=nbmt)
|
|
|
|
m2 = FksToBooleans.objects.create(bf=bmf, nbf=nbmf)
|
|
|
|
|
|
|
|
# select_related('fk_field_name')
|
|
|
|
ma = FksToBooleans.objects.select_related("bf").get(pk=m1.id)
|
2016-06-17 02:19:18 +08:00
|
|
|
self.assertIs(ma.bf.bfield, True)
|
|
|
|
self.assertIs(ma.nbf.nbfield, True)
|
2016-03-22 09:06:54 +08:00
|
|
|
|
|
|
|
# select_related()
|
|
|
|
mb = FksToBooleans.objects.select_related().get(pk=m1.id)
|
|
|
|
mc = FksToBooleans.objects.select_related().get(pk=m2.id)
|
2016-06-17 02:19:18 +08:00
|
|
|
self.assertIs(mb.bf.bfield, True)
|
|
|
|
self.assertIs(mb.nbf.nbfield, True)
|
|
|
|
self.assertIs(mc.bf.bfield, False)
|
|
|
|
self.assertIs(mc.nbf.nbfield, False)
|
2016-03-22 09:06:54 +08:00
|
|
|
|
|
|
|
def test_null_default(self):
|
|
|
|
"""
|
|
|
|
A BooleanField defaults to None, which isn't a valid value (#15124).
|
|
|
|
"""
|
|
|
|
boolean_field = BooleanModel._meta.get_field("bfield")
|
|
|
|
self.assertFalse(boolean_field.has_default())
|
|
|
|
b = BooleanModel()
|
|
|
|
self.assertIsNone(b.bfield)
|
|
|
|
with transaction.atomic():
|
|
|
|
with self.assertRaises(IntegrityError):
|
|
|
|
b.save()
|
|
|
|
|
|
|
|
nb = NullBooleanModel()
|
|
|
|
self.assertIsNone(nb.nbfield)
|
|
|
|
nb.save() # no error
|
|
|
|
|
|
|
|
|
|
|
|
class ValidationTest(SimpleTestCase):
|
|
|
|
def test_boolean_field_doesnt_accept_empty_input(self):
|
|
|
|
f = models.BooleanField()
|
|
|
|
with self.assertRaises(ValidationError):
|
|
|
|
f.clean(None, None)
|
|
|
|
|
|
|
|
def test_nullbooleanfield_blank(self):
|
|
|
|
"""
|
|
|
|
NullBooleanField shouldn't throw a validation error when given a value
|
|
|
|
of None.
|
|
|
|
"""
|
2021-01-14 04:28:09 +08:00
|
|
|
nullboolean = NullBooleanModel(nbfield=None)
|
2016-03-22 09:06:54 +08:00
|
|
|
nullboolean.full_clean()
|