Fixed #19299 -- Fixed Nullification of Foreign Keys To CharFields
Thanks tunixman for the report and Baptiste Mispelon and Shai Berger for reviews.
This commit is contained in:
parent
4d4e0ea461
commit
8bbdcc76e4
1
AUTHORS
1
AUTHORS
|
@ -646,6 +646,7 @@ answer newbie questions, and generally made Django that much better:
|
||||||
Rick Wagner <rwagner@physics.ucsd.edu>
|
Rick Wagner <rwagner@physics.ucsd.edu>
|
||||||
Gavin Wahl <gavinwahl@gmail.com>
|
Gavin Wahl <gavinwahl@gmail.com>
|
||||||
wam-djangobug@wamber.net
|
wam-djangobug@wamber.net
|
||||||
|
Albert Wang <aywang31@gmail.com>
|
||||||
Wang Chun <wangchun@exoweb.net>
|
Wang Chun <wangchun@exoweb.net>
|
||||||
Filip Wasilewski <filip.wasilewski@gmail.com>
|
Filip Wasilewski <filip.wasilewski@gmail.com>
|
||||||
Dan Watson <http://danwatson.net/>
|
Dan Watson <http://danwatson.net/>
|
||||||
|
|
|
@ -1692,11 +1692,12 @@ class ForeignKey(ForeignObject):
|
||||||
return field_default
|
return field_default
|
||||||
|
|
||||||
def get_db_prep_save(self, value, connection):
|
def get_db_prep_save(self, value, connection):
|
||||||
if value == '' or value is None:
|
if value is None or (value == '' and
|
||||||
|
(not self.related_field.empty_strings_allowed or
|
||||||
|
connection.features.interprets_empty_strings_as_nulls)):
|
||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
return self.related_field.get_db_prep_save(value,
|
return self.related_field.get_db_prep_save(value, connection=connection)
|
||||||
connection=connection)
|
|
||||||
|
|
||||||
def value_to_string(self, obj):
|
def value_to_string(self, obj):
|
||||||
if not obj:
|
if not obj:
|
||||||
|
|
|
@ -1416,9 +1416,12 @@ def get_cached_row(row, index_start, using, klass_info, offset=0,
|
||||||
klass, field_names, field_count, related_fields, reverse_related_fields, pk_idx = klass_info
|
klass, field_names, field_count, related_fields, reverse_related_fields, pk_idx = klass_info
|
||||||
|
|
||||||
fields = row[index_start:index_start + field_count]
|
fields = row[index_start:index_start + field_count]
|
||||||
# If the pk column is None (or the Oracle equivalent ''), then the related
|
# If the pk column is None (or the equivalent '' in the case the
|
||||||
|
# connection interprets empty strings as nulls), then the related
|
||||||
# object must be non-existent - set the relation to None.
|
# object must be non-existent - set the relation to None.
|
||||||
if fields[pk_idx] is None or fields[pk_idx] == '':
|
if (fields[pk_idx] is None or
|
||||||
|
(connections[using].features.interprets_empty_strings_as_nulls and
|
||||||
|
fields[pk_idx] == '')):
|
||||||
obj = None
|
obj = None
|
||||||
elif field_names:
|
elif field_names:
|
||||||
fields = list(fields)
|
fields = list(fields)
|
||||||
|
|
|
@ -72,12 +72,21 @@ class BooleanModel(models.Model):
|
||||||
string = models.CharField(max_length=10, default='abc')
|
string = models.CharField(max_length=10, default='abc')
|
||||||
|
|
||||||
|
|
||||||
|
class PrimaryKeyCharModel(models.Model):
|
||||||
|
string = models.CharField(max_length=10, primary_key=True)
|
||||||
|
|
||||||
|
|
||||||
class FksToBooleans(models.Model):
|
class FksToBooleans(models.Model):
|
||||||
"""Model wih FKs to models with {Null,}BooleanField's, #15040"""
|
"""Model wih FKs to models with {Null,}BooleanField's, #15040"""
|
||||||
bf = models.ForeignKey(BooleanModel)
|
bf = models.ForeignKey(BooleanModel)
|
||||||
nbf = models.ForeignKey(NullBooleanModel)
|
nbf = models.ForeignKey(NullBooleanModel)
|
||||||
|
|
||||||
|
|
||||||
|
class FkToChar(models.Model):
|
||||||
|
"""Model with FK to a model with a CharField primary key, #19299"""
|
||||||
|
out = models.ForeignKey(PrimaryKeyCharModel)
|
||||||
|
|
||||||
|
|
||||||
class RenamedField(models.Model):
|
class RenamedField(models.Model):
|
||||||
modelname = models.IntegerField(name="fieldname", choices=((1, 'One'),))
|
modelname = models.IntegerField(name="fieldname", choices=((1, 'One'),))
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,8 @@ from django.utils.functional import lazy
|
||||||
|
|
||||||
from .models import (
|
from .models import (
|
||||||
Foo, Bar, Whiz, BigD, BigS, BigInt, Post, NullBooleanModel,
|
Foo, Bar, Whiz, BigD, BigS, BigInt, Post, NullBooleanModel,
|
||||||
BooleanModel, DataModel, Document, RenamedField,
|
BooleanModel, PrimaryKeyCharModel, DataModel, Document, RenamedField,
|
||||||
VerboseNameField, FksToBooleans)
|
VerboseNameField, FksToBooleans, FkToChar)
|
||||||
|
|
||||||
|
|
||||||
class BasicFieldTests(test.TestCase):
|
class BasicFieldTests(test.TestCase):
|
||||||
|
@ -146,6 +146,17 @@ class ForeignKeyTests(test.TestCase):
|
||||||
b = Bar.objects.create(b="bcd")
|
b = Bar.objects.create(b="bcd")
|
||||||
self.assertEqual(b.a, a)
|
self.assertEqual(b.a, a)
|
||||||
|
|
||||||
|
@test.skipIfDBFeature('interprets_empty_strings_as_nulls')
|
||||||
|
def test_empty_string_fk(self):
|
||||||
|
"""
|
||||||
|
Test that foreign key values to empty strings don't get converted
|
||||||
|
to None (#19299)
|
||||||
|
"""
|
||||||
|
char_model_empty = PrimaryKeyCharModel.objects.create(string='')
|
||||||
|
fk_model_empty = FkToChar.objects.create(out=char_model_empty)
|
||||||
|
fk_model_empty = FkToChar.objects.select_related('out').get(id=fk_model_empty.pk)
|
||||||
|
self.assertEqual(fk_model_empty.out, char_model_empty)
|
||||||
|
|
||||||
|
|
||||||
class DateTimeFieldTests(unittest.TestCase):
|
class DateTimeFieldTests(unittest.TestCase):
|
||||||
def test_datetimefield_to_python_usecs(self):
|
def test_datetimefield_to_python_usecs(self):
|
||||||
|
|
Loading…
Reference in New Issue