Loading django/db/models/sql/compiler.py +11 −1 Original line number Diff line number Diff line Loading @@ -774,10 +774,20 @@ class SQLCompiler(object): # 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() Loading tests/regressiontests/model_fields/models.py +5 −0 Original line number Diff line number Diff line Loading @@ -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'),)) Loading tests/regressiontests/model_fields/tests.py +39 −1 Original line number Diff line number Diff line Loading @@ -12,7 +12,8 @@ from django.utils import six 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, Loading Loading @@ -218,6 +219,43 @@ class BooleanFieldTests(unittest.TestCase): 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): """ Loading Loading
django/db/models/sql/compiler.py +11 −1 Original line number Diff line number Diff line Loading @@ -774,10 +774,20 @@ class SQLCompiler(object): # 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() Loading
tests/regressiontests/model_fields/models.py +5 −0 Original line number Diff line number Diff line Loading @@ -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'),)) Loading
tests/regressiontests/model_fields/tests.py +39 −1 Original line number Diff line number Diff line Loading @@ -12,7 +12,8 @@ from django.utils import six 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, Loading Loading @@ -218,6 +219,43 @@ class BooleanFieldTests(unittest.TestCase): 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): """ Loading