Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixed #15040 - Boolean fields return 0 and 1 when loaded through sele…

…ct_related

Thanks to homm for the report and ramiro for the patch.
  • Loading branch information...
commit f3a2bcdee906f7ca1434b6275fdc09b3a454cf46 1 parent 5c143cb
@spookylukey spookylukey authored
View
12 django/db/models/sql/compiler.py
@@ -774,10 +774,20 @@ def results_iter(self):
# We only set this up here because
# related_select_fields isn't populated until
# execute_sql() has been called.
+
+ # We also include types of fields of related models that
+ # will be included via select_related() for the benefit
+ # of MySQL/MySQLdb when boolean fields are involved
+ # (#15040).
+
+ # This code duplicates the logic for the order of fields
+ # found in get_columns(). It would be nice to clean this up.
if self.query.select_fields:
- fields = self.query.select_fields + self.query.related_select_fields
+ fields = self.query.select_fields
else:
fields = self.query.model._meta.fields
+ fields = fields + self.query.related_select_fields
+
# If the field was deferred, exclude it from being passed
# into `resolve_columns` because it wasn't selected.
only_load = self.deferred_to_columns()
View
5 tests/regressiontests/model_fields/models.py
@@ -66,6 +66,11 @@ class BooleanModel(models.Model):
bfield = models.BooleanField()
string = models.CharField(max_length=10, default='abc')
+class FksToBooleans(models.Model):
+ """Model wih FKs to models with {Null,}BooleanField's, #15040"""
+ bf = models.ForeignKey(BooleanModel)
+ nbf = models.ForeignKey(NullBooleanModel)
+
class RenamedField(models.Model):
modelname = models.IntegerField(name="fieldname", choices=((1,'One'),))
View
40 tests/regressiontests/model_fields/tests.py
@@ -12,7 +12,8 @@
from django.utils import unittest
from .models import (Foo, Bar, Whiz, BigD, BigS, Image, BigInt, Post,
- NullBooleanModel, BooleanModel, Document, RenamedField, VerboseNameField)
+ NullBooleanModel, BooleanModel, Document, RenamedField, VerboseNameField,
+ FksToBooleans)
from .imagefield import (ImageFieldTests, ImageFieldTwoDimensionsTests,
TwoImageFieldTests, ImageFieldNoDimensionsTests,
@@ -218,6 +219,43 @@ def test_return_type(self):
select={'string_col': 'string'})[0]
self.assertFalse(isinstance(b5.pk, bool))
+ def test_select_related(self):
+ """
+ Test type of boolean fields when retrieved via select_related() (MySQL,
+ #15040)
+ """
+ bmt = BooleanModel.objects.create(bfield=True)
+ bmf = BooleanModel.objects.create(bfield=False)
+ nbmt = NullBooleanModel.objects.create(nbfield=True)
+ nbmf = NullBooleanModel.objects.create(nbfield=False)
+
+ m1 = FksToBooleans.objects.create(bf=bmt, nbf=nbmt)
+ m2 = FksToBooleans.objects.create(bf=bmf, nbf=nbmf)
+
+ # Test select_related('fk_field_name')
+ ma = FksToBooleans.objects.select_related('bf').get(pk=m1.id)
+ # verify types -- should't be 0/1
+ self.assertIsInstance(ma.bf.bfield, bool)
+ self.assertIsInstance(ma.nbf.nbfield, bool)
+ # verify values
+ self.assertEqual(ma.bf.bfield, True)
+ self.assertEqual(ma.nbf.nbfield, True)
+
+ # Test select_related()
+ mb = FksToBooleans.objects.select_related().get(pk=m1.id)
+ mc = FksToBooleans.objects.select_related().get(pk=m2.id)
+ # verify types -- shouldn't be 0/1
+ self.assertIsInstance(mb.bf.bfield, bool)
+ self.assertIsInstance(mb.nbf.nbfield, bool)
+ self.assertIsInstance(mc.bf.bfield, bool)
+ self.assertIsInstance(mc.nbf.nbfield, bool)
+ # verify values
+ self.assertEqual(mb.bf.bfield, True)
+ self.assertEqual(mb.nbf.nbfield, True)
+ self.assertEqual(mc.bf.bfield, False)
+ self.assertEqual(mc.nbf.nbfield, False)
+
+
class ChoicesTests(test.TestCase):
def test_choices_and_field_display(self):
"""
Please sign in to comment.
Something went wrong with that request. Please try again.