Skip to content

Commit a75dc34

Browse files
committed
Fixed #13250 -- Corrected a problem with the use of routing rules on the create() call on a Foreign Key. Thanks to [email protected] for the report.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@12895 bcc190cf-cafb-0310-a4f2-bffc1f526a37
1 parent 9a8a15e commit a75dc34

File tree

3 files changed

+38
-3
lines changed

3 files changed

+38
-3
lines changed

django/contrib/contenttypes/generic.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from django.core.exceptions import ObjectDoesNotExist
66
from django.db import connection
77
from django.db.models import signals
8-
from django.db import models
8+
from django.db import models, router
99
from django.db.models.fields.related import RelatedField, Field, ManyToManyRel
1010
from django.db.models.loading import get_model
1111
from django.forms import ModelForm
@@ -271,7 +271,8 @@ def clear(self):
271271
def create(self, **kwargs):
272272
kwargs[self.content_type_field_name] = self.content_type
273273
kwargs[self.object_id_field_name] = self.pk_val
274-
return super(GenericRelatedObjectManager, self).create(**kwargs)
274+
db = router.db_for_write(self.model, instance=self.instance)
275+
return super(GenericRelatedObjectManager, self).using(db).create(**kwargs)
275276
create.alters_data = True
276277

277278
return GenericRelatedObjectManager

django/db/models/fields/related.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,8 @@ def add(self, *objs):
419419

420420
def create(self, **kwargs):
421421
kwargs.update({rel_field.name: instance})
422-
return super(RelatedManager, self).create(**kwargs)
422+
db = router.db_for_write(rel_model, instance=instance)
423+
return super(RelatedManager, self).using(db).create(**kwargs)
423424
create.alters_data = True
424425

425426
def get_or_create(self, **kwargs):

tests/regressiontests/multiple_database/tests.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -971,6 +971,19 @@ def test_foreign_key_cross_database_protection(self):
971971
water = Book(title="Dive into Water", published=datetime.date(2001, 1, 1), editor=mark)
972972
self.assertEquals(water._state.db, 'default')
973973

974+
# If you create an object through a FK relation, it will be
975+
# written to the write database, even if the original object
976+
# was on the read database
977+
cheesecake = mark.edited.create(title='Dive into Cheesecake', published=datetime.date(2010, 3, 15))
978+
self.assertEquals(cheesecake._state.db, 'default')
979+
980+
# Same goes for get_or_create, regardless of whether getting or creating
981+
cheesecake, created = mark.edited.get_or_create(title='Dive into Cheesecake', published=datetime.date(2010, 3, 15))
982+
self.assertEquals(cheesecake._state.db, 'default')
983+
984+
puddles, created = mark.edited.get_or_create(title='Dive into Puddles', published=datetime.date(2010, 3, 15))
985+
self.assertEquals(puddles._state.db, 'default')
986+
974987
def test_m2m_cross_database_protection(self):
975988
"M2M relations can cross databases if the database share a source"
976989
# Create books and authors on the inverse to the usual database
@@ -1074,6 +1087,19 @@ def test_m2m_cross_database_protection(self):
10741087
self.assertEquals(Book.authors.through.objects.using('default').count(), 1)
10751088
self.assertEquals(Book.authors.through.objects.using('other').count(), 0)
10761089

1090+
# If you create an object through a M2M relation, it will be
1091+
# written to the write database, even if the original object
1092+
# was on the read database
1093+
alice = dive.authors.create(name='Alice')
1094+
self.assertEquals(alice._state.db, 'default')
1095+
1096+
# Same goes for get_or_create, regardless of whether getting or creating
1097+
alice, created = dive.authors.get_or_create(name='Alice')
1098+
self.assertEquals(alice._state.db, 'default')
1099+
1100+
bob, created = dive.authors.get_or_create(name='Bob')
1101+
self.assertEquals(bob._state.db, 'default')
1102+
10771103
def test_generic_key_cross_database_protection(self):
10781104
"Generic Key operations can span databases if they share a source"
10791105
# Create a book and author on the default database
@@ -1150,6 +1176,13 @@ def test_generic_key_cross_database_protection(self):
11501176
review3.content_object = dive
11511177
self.assertEquals(review3._state.db, 'default')
11521178

1179+
# If you create an object through a M2M relation, it will be
1180+
# written to the write database, even if the original object
1181+
# was on the read database
1182+
dive = Book.objects.using('other').get(title='Dive into Python')
1183+
nyt = dive.reviews.create(source="New York Times", content_object=dive)
1184+
self.assertEquals(nyt._state.db, 'default')
1185+
11531186
def test_subquery(self):
11541187
"""Make sure as_sql works with subqueries and master/slave."""
11551188
# Create a book and author on the other database

0 commit comments

Comments
 (0)