Fixed #15040 - Boolean fields return 0 and 1 when loaded through select_related
Thanks to homm for the report and ramiro for the patch.
This commit is contained in:
parent
5c143cb340
commit
f3a2bcdee9
|
@ -774,10 +774,20 @@ class SQLCompiler(object):
|
||||||
# We only set this up here because
|
# We only set this up here because
|
||||||
# related_select_fields isn't populated until
|
# related_select_fields isn't populated until
|
||||||
# execute_sql() has been called.
|
# 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:
|
if self.query.select_fields:
|
||||||
fields = self.query.select_fields + self.query.related_select_fields
|
fields = self.query.select_fields
|
||||||
else:
|
else:
|
||||||
fields = self.query.model._meta.fields
|
fields = self.query.model._meta.fields
|
||||||
|
fields = fields + self.query.related_select_fields
|
||||||
|
|
||||||
# If the field was deferred, exclude it from being passed
|
# If the field was deferred, exclude it from being passed
|
||||||
# into `resolve_columns` because it wasn't selected.
|
# into `resolve_columns` because it wasn't selected.
|
||||||
only_load = self.deferred_to_columns()
|
only_load = self.deferred_to_columns()
|
||||||
|
|
|
@ -66,6 +66,11 @@ class BooleanModel(models.Model):
|
||||||
bfield = models.BooleanField()
|
bfield = models.BooleanField()
|
||||||
string = models.CharField(max_length=10, default='abc')
|
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):
|
class RenamedField(models.Model):
|
||||||
modelname = models.IntegerField(name="fieldname", choices=((1,'One'),))
|
modelname = models.IntegerField(name="fieldname", choices=((1,'One'),))
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,8 @@ from django.utils import six
|
||||||
from django.utils import unittest
|
from django.utils import unittest
|
||||||
|
|
||||||
from .models import (Foo, Bar, Whiz, BigD, BigS, Image, BigInt, Post,
|
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,
|
from .imagefield import (ImageFieldTests, ImageFieldTwoDimensionsTests,
|
||||||
TwoImageFieldTests, ImageFieldNoDimensionsTests,
|
TwoImageFieldTests, ImageFieldNoDimensionsTests,
|
||||||
|
@ -218,6 +219,43 @@ class BooleanFieldTests(unittest.TestCase):
|
||||||
select={'string_col': 'string'})[0]
|
select={'string_col': 'string'})[0]
|
||||||
self.assertFalse(isinstance(b5.pk, bool))
|
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):
|
class ChoicesTests(test.TestCase):
|
||||||
def test_choices_and_field_display(self):
|
def test_choices_and_field_display(self):
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in New Issue