Fixed #13250 -- Corrected a problem with the use of routing rules on the create() call on a Foreign Key. Thanks to chris@xlevus.net for the report.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@12895 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Russell Keith-Magee 2010-03-31 12:33:10 +00:00
parent 9a8a15ecbb
commit a75dc3406f
3 changed files with 38 additions and 3 deletions

View File

@ -5,7 +5,7 @@ Classes allowing "generic" relations through ContentType and object-id fields.
from django.core.exceptions import ObjectDoesNotExist
from django.db import connection
from django.db.models import signals
from django.db import models
from django.db import models, router
from django.db.models.fields.related import RelatedField, Field, ManyToManyRel
from django.db.models.loading import get_model
from django.forms import ModelForm
@ -271,7 +271,8 @@ def create_generic_related_manager(superclass):
def create(self, **kwargs):
kwargs[self.content_type_field_name] = self.content_type
kwargs[self.object_id_field_name] = self.pk_val
return super(GenericRelatedObjectManager, self).create(**kwargs)
db = router.db_for_write(self.model, instance=self.instance)
return super(GenericRelatedObjectManager, self).using(db).create(**kwargs)
create.alters_data = True
return GenericRelatedObjectManager

View File

@ -419,7 +419,8 @@ class ForeignRelatedObjectsDescriptor(object):
def create(self, **kwargs):
kwargs.update({rel_field.name: instance})
return super(RelatedManager, self).create(**kwargs)
db = router.db_for_write(rel_model, instance=instance)
return super(RelatedManager, self).using(db).create(**kwargs)
create.alters_data = True
def get_or_create(self, **kwargs):

View File

@ -971,6 +971,19 @@ class RouterTestCase(TestCase):
water = Book(title="Dive into Water", published=datetime.date(2001, 1, 1), editor=mark)
self.assertEquals(water._state.db, 'default')
# If you create an object through a FK relation, it will be
# written to the write database, even if the original object
# was on the read database
cheesecake = mark.edited.create(title='Dive into Cheesecake', published=datetime.date(2010, 3, 15))
self.assertEquals(cheesecake._state.db, 'default')
# Same goes for get_or_create, regardless of whether getting or creating
cheesecake, created = mark.edited.get_or_create(title='Dive into Cheesecake', published=datetime.date(2010, 3, 15))
self.assertEquals(cheesecake._state.db, 'default')
puddles, created = mark.edited.get_or_create(title='Dive into Puddles', published=datetime.date(2010, 3, 15))
self.assertEquals(puddles._state.db, 'default')
def test_m2m_cross_database_protection(self):
"M2M relations can cross databases if the database share a source"
# Create books and authors on the inverse to the usual database
@ -1074,6 +1087,19 @@ class RouterTestCase(TestCase):
self.assertEquals(Book.authors.through.objects.using('default').count(), 1)
self.assertEquals(Book.authors.through.objects.using('other').count(), 0)
# If you create an object through a M2M relation, it will be
# written to the write database, even if the original object
# was on the read database
alice = dive.authors.create(name='Alice')
self.assertEquals(alice._state.db, 'default')
# Same goes for get_or_create, regardless of whether getting or creating
alice, created = dive.authors.get_or_create(name='Alice')
self.assertEquals(alice._state.db, 'default')
bob, created = dive.authors.get_or_create(name='Bob')
self.assertEquals(bob._state.db, 'default')
def test_generic_key_cross_database_protection(self):
"Generic Key operations can span databases if they share a source"
# Create a book and author on the default database
@ -1150,6 +1176,13 @@ class RouterTestCase(TestCase):
review3.content_object = dive
self.assertEquals(review3._state.db, 'default')
# If you create an object through a M2M relation, it will be
# written to the write database, even if the original object
# was on the read database
dive = Book.objects.using('other').get(title='Dive into Python')
nyt = dive.reviews.create(source="New York Times", content_object=dive)
self.assertEquals(nyt._state.db, 'default')
def test_subquery(self):
"""Make sure as_sql works with subqueries and master/slave."""
# Create a book and author on the other database