Code

Ticket #7190: django-real-bools.4.diff

File django-real-bools.4.diff, 5.9 KB (added by Alex, 4 years ago)
Line 
1diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py
2index 05f16db..02c69c2 100644
3--- a/django/db/models/fields/__init__.py
4+++ b/django/db/models/fields/__init__.py
5@@ -524,9 +524,14 @@ class BooleanField(Field):
6         return "BooleanField"
7 
8     def to_python(self, value):
9-        if value in (True, False): return value
10-        if value in ('t', 'True', '1'): return True
11-        if value in ('f', 'False', '0'): return False
12+        if value in (True, False):
13+            # if value is 1 or 0 than it's equal to True or False, but we want
14+            # to return a true bool for semantic reasons.
15+            return bool(value)
16+        if value in ('t', 'True', '1'):
17+            return True
18+        if value in ('f', 'False', '0'):
19+            return False
20         raise exceptions.ValidationError(self.error_messages['invalid'])
21 
22     def get_prep_lookup(self, lookup_type, value):
23@@ -934,10 +939,16 @@ class NullBooleanField(Field):
24         return "NullBooleanField"
25 
26     def to_python(self, value):
27-        if value in (None, True, False): return value
28-        if value in ('None',): return None
29-        if value in ('t', 'True', '1'): return True
30-        if value in ('f', 'False', '0'): return False
31+        if value is None:
32+            return None
33+        if value in (True, False):
34+            return bool(value)
35+        if value in ('None',):
36+            return None
37+        if value in ('t', 'True', '1'):
38+            return True
39+        if value in ('f', 'False', '0'):
40+            return False
41         raise exceptions.ValidationError(self.error_messages['invalid'])
42 
43     def get_prep_lookup(self, lookup_type, value):
44diff --git a/docs/ref/databases.txt b/docs/ref/databases.txt
45index afead83..3a7c3ea 100644
46--- a/docs/ref/databases.txt
47+++ b/docs/ref/databases.txt
48@@ -326,12 +326,11 @@ Notes on specific fields
49 Boolean fields
50 ~~~~~~~~~~~~~~
51 
52-Since MySQL doesn't have a direct ``BOOLEAN`` column type, Django uses a
53-``TINYINT`` column with values of ``1`` and ``0`` to store values for the
54-:class:`~django.db.models.BooleanField` model field. Refer to the documentation
55-of that field for more details, but usually this won't be something that will
56-matter unless you're printing out the field values and are expecting to see
57-``True`` and ``False.``.
58+.. versionchanged:: 1.2
59+
60+In previous versions of Django when running under MySQL ``BooleanFields`` would
61+return their data as ``ints``, instead of true ``bools``.  See the release
62+notes for a complete description of the change.
63 
64 Character fields
65 ~~~~~~~~~~~~~~~~
66diff --git a/docs/ref/models/fields.txt b/docs/ref/models/fields.txt
67index cd66c46..e824cf7 100644
68--- a/docs/ref/models/fields.txt
69+++ b/docs/ref/models/fields.txt
70@@ -342,18 +342,11 @@ A true/false field.
71 
72 The admin represents this as a checkbox.
73 
74-.. admonition:: MySQL users..
75-
76-    A boolean field in MySQL is stored as a ``TINYINT`` column with a value of
77-    either 0 or 1 (most databases have a proper ``BOOLEAN`` type instead). So,
78-    for MySQL, only, when a ``BooleanField`` is retrieved from the database
79-    and stored on a model attribute, it will have the values 1 or 0, rather
80-    than ``True`` or ``False``. Normally, this shouldn't be a problem, since
81-    Python guarantees that ``1 == True`` and ``0 == False`` are both true.
82-    Just be careful if you're writing something like ``obj is True`` when
83-    ``obj`` is a value from a boolean attribute on a model. If that model was
84-    constructed using the ``mysql`` backend, the "``is``" test will fail.
85-    Prefer an equality test (using "``==``") in cases like this.
86+.. versionchanged:: 1.2
87+   
88+    In previous versions of Django when running under MySQL ``BooleanFields``
89+    would return their data as ``ints``, instead of true ``bools``.  See the
90+    release notes for a complete description of the change.
91 
92 ``CharField``
93 -------------
94diff --git a/docs/releases/1.2.txt b/docs/releases/1.2.txt
95index b952ec1..703ded3 100644
96--- a/docs/releases/1.2.txt
97+++ b/docs/releases/1.2.txt
98@@ -302,6 +302,16 @@ created using ``decorator_from_middleware``.
99 
100 .. _deprecated-features-1.2:
101 
102+``BooleanField`` on MySQL
103+--------------------------
104+
105+In previous versions of Django ``BoleanFields`` under MySQL would return their
106+values as either ``1`` or ``0``, instead of ``True`` or ``False``.  For most
107+people this shouldn't have been a problem because ``bool`` is a subclass of
108+``int``, however in Django 1.2 MySQL correctly returns a real ``bool``.  The
109+only time this should ever be an issue is if you were expecting printing the
110+``repr`` of a ``BooleanField`` to print ``1`` or ``0``.
111+
112 Features deprecated in 1.2
113 ==========================
114 
115diff --git a/tests/regressiontests/model_fields/tests.py b/tests/regressiontests/model_fields/tests.py
116index 18bfbd3..1ee92d4 100644
117--- a/tests/regressiontests/model_fields/tests.py
118+++ b/tests/regressiontests/model_fields/tests.py
119@@ -107,12 +107,22 @@ class BooleanFieldTests(unittest.TestCase):
120         self.assertEqual(f.get_db_prep_lookup('exact', '0', connection=connection), [False])
121         self.assertEqual(f.get_db_prep_lookup('exact', 0, connection=connection), [False])
122         self.assertEqual(f.get_db_prep_lookup('exact', None, connection=connection), [None])
123+   
124+    def _test_to_python(self, f):
125+        self.assertTrue(f.to_python(1) is True)
126+        self.assertTrue(f.to_python(0) is False)
127 
128     def test_booleanfield_get_db_prep_lookup(self):
129         self._test_get_db_prep_lookup(models.BooleanField())
130 
131     def test_nullbooleanfield_get_db_prep_lookup(self):
132         self._test_get_db_prep_lookup(models.NullBooleanField())
133+   
134+    def test_booleanfield_to_python(self):
135+        self._test_to_python(models.BooleanField())
136+   
137+    def test_nullbooleanfield_to_python(self):
138+        self._test_to_python(models.NullBooleanField())
139 
140     def test_booleanfield_choices_blank(self):
141         """