1from __future__ import annotations
2
3from typing import Any
4
5from plain import exceptions
6
7from .base import DefaultableField
8
9
10class BooleanField(DefaultableField[bool]):
11 db_type_sql = "boolean"
12 empty_strings_allowed = False
13
14 def to_python(self, value: Any) -> bool | None:
15 if self.allow_null and value in self.empty_values:
16 return None
17 if value in (True, False):
18 # 1/0 are equal to True/False. bool() converts former to latter.
19 return bool(value)
20 if value in ("t", "True", "1"):
21 return True
22 if value in ("f", "False", "0"):
23 return False
24 if self.allow_null:
25 message = '"%(value)s" value must be either True, False, or None.'
26 else:
27 message = '"%(value)s" value must be either True or False.'
28 raise exceptions.ValidationError(
29 message,
30 code="invalid",
31 params={"value": value},
32 )
33
34 def get_prep_value(self, value: Any) -> Any:
35 value = super().get_prep_value(value)
36 if value is None:
37 return None
38 return self.to_python(value)