Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixed #13668 -- Corrected database router methods invocation for Many…

…ToMany fields without through models. Thanks craig.kimerer for the report and David Gouldin for the fix.

This also adds tests for r14857.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@15185 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit e1ede214e6dd0fc988fa572d8be45231c275970c 1 parent fd12e3b
@ramiro ramiro authored
View
6 django/db/models/fields/related.py
@@ -555,7 +555,7 @@ def _add_items(self, source_field_name, target_field_name, *objs):
raise TypeError("'%s' instance expected" % self.model._meta.object_name)
else:
new_ids.add(obj)
- db = router.db_for_write(self.through.__class__, instance=self.instance)
+ db = router.db_for_write(self.through, instance=self.instance)
vals = self.through._default_manager.using(db).values_list(target_field_name, flat=True)
vals = vals.filter(**{
source_field_name: self._pk_val,
@@ -597,7 +597,7 @@ def _remove_items(self, source_field_name, target_field_name, *objs):
else:
old_ids.add(obj)
# Work out what DB we're operating on
- db = router.db_for_write(self.through.__class__, instance=self.instance)
+ db = router.db_for_write(self.through, instance=self.instance)
# Send a signal to the other end if need be.
if self.reverse or source_field_name == self.source_field_name:
# Don't send the signal when we are deleting the
@@ -618,7 +618,7 @@ def _remove_items(self, source_field_name, target_field_name, *objs):
model=self.model, pk_set=old_ids, using=db)
def _clear_items(self, source_field_name):
- db = router.db_for_write(self.through.__class__, instance=self.instance)
+ db = router.db_for_write(self.through, instance=self.instance)
# source_col_name: the PK colname in join_table for the source object
if self.reverse or source_field_name == self.source_field_name:
# Don't send the signal when we are clearing the
View
53 tests/regressiontests/multiple_database/tests.py
@@ -1791,3 +1791,56 @@ def test_database_arg_m2m(self):
b.authors.clear()
self._write_to_default()
self.assertEqual(receiver._database, "other")
+
+class AttributeErrorRouter(object):
+ "A router to test the exception handling of ConnectionRouter"
+ def db_for_read(self, model, **hints):
+ raise AttributeError
+
+ def db_for_write(self, model, **hints):
+ raise AttributeError
+
+class RouterAttributeErrorTestCase(TestCase):
+ multi_db = True
+
+ def setUp(self):
+ self.old_routers = router.routers
+ router.routers = [AttributeErrorRouter()]
+
+ def tearDown(self):
+ router.routers = self.old_routers
+
+ def test_attribute_error(self):
+ "Check that the AttributeError from AttributeErrorRouter bubbles up"
+ dive = Book()
+ dive.title="Dive into Python"
+ dive.published = datetime.date(2009, 5, 4)
+ self.assertRaises(AttributeError, dive.save)
+
+class ModelMetaRouter(object):
+ "A router to ensure model arguments are real model classes"
+ def db_for_write(self, model, **hints):
+ if not hasattr(model, '_meta'):
+ raise ValueError
+
+class RouterM2MThroughTestCase(TestCase):
+ multi_db = True
+
+ def setUp(self):
+ self.old_routers = router.routers
+ router.routers = [ModelMetaRouter()]
+
+ def tearDown(self):
+ router.routers = self.old_routers
+
+ def test_m2m_through(self):
+ b = Book.objects.create(title="Pro Django",
+ published=datetime.date(2008, 12, 16))
+
+ p = Person.objects.create(name="Marty Alchin")
+ # test add
+ b.authors.add(p)
+ # test remove
+ b.authors.remove(p)
+ # test clear
+ b.authors.clear()
Please sign in to comment.
Something went wrong with that request. Please try again.