mirror of
				https://github.com/django/django.git
				synced 2025-10-31 01:25:32 +00:00 
			
		
		
		
	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:
		| @@ -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 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user