Fixed #13358 -- Ensured that db_manager() can be used to override database routing on M2M, reverse FK and generic key queries. Thanks to Craig Kimerer for the report.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@12993 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
94a968cfc6
commit
2cd48bac7e
|
@ -243,11 +243,12 @@ def create_generic_related_manager(superclass):
|
||||||
self.pk_val = self.instance._get_pk_val()
|
self.pk_val = self.instance._get_pk_val()
|
||||||
|
|
||||||
def get_query_set(self):
|
def get_query_set(self):
|
||||||
|
db = self._db or router.db_for_read(self.model, instance=self.instance)
|
||||||
query = {
|
query = {
|
||||||
'%s__pk' % self.content_type_field_name : self.content_type.id,
|
'%s__pk' % self.content_type_field_name : self.content_type.id,
|
||||||
'%s__exact' % self.object_id_field_name : self.pk_val,
|
'%s__exact' % self.object_id_field_name : self.pk_val,
|
||||||
}
|
}
|
||||||
return superclass.get_query_set(self).using(self.instance._state.db).filter(**query)
|
return superclass.get_query_set(self).using(db).filter(**query)
|
||||||
|
|
||||||
def add(self, *objs):
|
def add(self, *objs):
|
||||||
for obj in objs:
|
for obj in objs:
|
||||||
|
@ -259,13 +260,15 @@ def create_generic_related_manager(superclass):
|
||||||
add.alters_data = True
|
add.alters_data = True
|
||||||
|
|
||||||
def remove(self, *objs):
|
def remove(self, *objs):
|
||||||
|
db = router.db_for_write(self.model, instance=self.instance)
|
||||||
for obj in objs:
|
for obj in objs:
|
||||||
obj.delete(using=self.instance._state.db)
|
obj.delete(using=db)
|
||||||
remove.alters_data = True
|
remove.alters_data = True
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
|
db = router.db_for_write(self.model, instance=self.instance)
|
||||||
for obj in self.all():
|
for obj in self.all():
|
||||||
obj.delete(using=self.instance._state.db)
|
obj.delete(using=db)
|
||||||
clear.alters_data = True
|
clear.alters_data = True
|
||||||
|
|
||||||
def create(self, **kwargs):
|
def create(self, **kwargs):
|
||||||
|
|
|
@ -406,7 +406,7 @@ class ForeignRelatedObjectsDescriptor(object):
|
||||||
|
|
||||||
class RelatedManager(superclass):
|
class RelatedManager(superclass):
|
||||||
def get_query_set(self):
|
def get_query_set(self):
|
||||||
db = router.db_for_read(rel_model, instance=instance)
|
db = self._db or router.db_for_read(rel_model, instance=instance)
|
||||||
return superclass.get_query_set(self).using(db).filter(**(self.core_filters))
|
return superclass.get_query_set(self).using(db).filter(**(self.core_filters))
|
||||||
|
|
||||||
def add(self, *objs):
|
def add(self, *objs):
|
||||||
|
@ -480,7 +480,7 @@ def create_many_related_manager(superclass, rel=False):
|
||||||
raise ValueError("%r instance needs to have a primary key value before a many-to-many relationship can be used." % instance.__class__.__name__)
|
raise ValueError("%r instance needs to have a primary key value before a many-to-many relationship can be used." % instance.__class__.__name__)
|
||||||
|
|
||||||
def get_query_set(self):
|
def get_query_set(self):
|
||||||
db = router.db_for_read(self.instance.__class__, instance=self.instance)
|
db = self._db or router.db_for_read(self.instance.__class__, instance=self.instance)
|
||||||
return superclass.get_query_set(self).using(db)._next_is_sticky().filter(**(self.core_filters))
|
return superclass.get_query_set(self).using(db)._next_is_sticky().filter(**(self.core_filters))
|
||||||
|
|
||||||
# If the ManyToMany relation has an intermediary model,
|
# If the ManyToMany relation has an intermediary model,
|
||||||
|
|
|
@ -1186,6 +1186,45 @@ class RouterTestCase(TestCase):
|
||||||
nyt = dive.reviews.create(source="New York Times", content_object=dive)
|
nyt = dive.reviews.create(source="New York Times", content_object=dive)
|
||||||
self.assertEquals(nyt._state.db, 'default')
|
self.assertEquals(nyt._state.db, 'default')
|
||||||
|
|
||||||
|
def test_m2m_managers(self):
|
||||||
|
"M2M relations are represented by managers, and can be controlled like managers"
|
||||||
|
pro = Book.objects.using('other').create(pk=1, title="Pro Django",
|
||||||
|
published=datetime.date(2008, 12, 16))
|
||||||
|
|
||||||
|
marty = Person.objects.using('other').create(pk=1, name="Marty Alchin")
|
||||||
|
pro.authors = [marty]
|
||||||
|
|
||||||
|
self.assertEquals(pro.authors.db, 'other')
|
||||||
|
self.assertEquals(pro.authors.db_manager('default').db, 'default')
|
||||||
|
self.assertEquals(pro.authors.db_manager('default').all().db, 'default')
|
||||||
|
|
||||||
|
self.assertEquals(marty.book_set.db, 'other')
|
||||||
|
self.assertEquals(marty.book_set.db_manager('default').db, 'default')
|
||||||
|
self.assertEquals(marty.book_set.db_manager('default').all().db, 'default')
|
||||||
|
|
||||||
|
def test_foreign_key_managers(self):
|
||||||
|
"FK reverse relations are represented by managers, and can be controlled like managers"
|
||||||
|
marty = Person.objects.using('other').create(pk=1, name="Marty Alchin")
|
||||||
|
pro = Book.objects.using('other').create(pk=1, title="Pro Django",
|
||||||
|
published=datetime.date(2008, 12, 16),
|
||||||
|
editor=marty)
|
||||||
|
|
||||||
|
self.assertEquals(marty.edited.db, 'other')
|
||||||
|
self.assertEquals(marty.edited.db_manager('default').db, 'default')
|
||||||
|
self.assertEquals(marty.edited.db_manager('default').all().db, 'default')
|
||||||
|
|
||||||
|
def test_generic_key_managers(self):
|
||||||
|
"Generic key relations are represented by managers, and can be controlled like managers"
|
||||||
|
pro = Book.objects.using('other').create(title="Pro Django",
|
||||||
|
published=datetime.date(2008, 12, 16))
|
||||||
|
|
||||||
|
review1 = Review.objects.using('other').create(source="Python Monthly",
|
||||||
|
content_object=pro)
|
||||||
|
|
||||||
|
self.assertEquals(pro.reviews.db, 'other')
|
||||||
|
self.assertEquals(pro.reviews.db_manager('default').db, 'default')
|
||||||
|
self.assertEquals(pro.reviews.db_manager('default').all().db, 'default')
|
||||||
|
|
||||||
def test_subquery(self):
|
def test_subquery(self):
|
||||||
"""Make sure as_sql works with subqueries and master/slave."""
|
"""Make sure as_sql works with subqueries and master/slave."""
|
||||||
# Create a book and author on the other database
|
# Create a book and author on the other database
|
||||||
|
|
Loading…
Reference in New Issue