Commit 857b49d1 authored by Ramiro Morales's avatar Ramiro Morales
Browse files

[1.2.X] Fixed #13668 -- Corrected database router methods invocation for...

[1.2.X] Fixed #13668 -- Corrected database router methods invocation for ManyToMany fields without through models. Thanks craig.kimerer for the report and David Gouldin for the fix.

This also adds tests for r14857.

Backport of [15185] from trunk.

git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.2.X@15186 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent 4d2708ff
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -553,7 +553,7 @@ def create_many_related_manager(superclass, rel=False):
                        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,
@@ -601,7 +601,7 @@ def create_many_related_manager(superclass, rel=False):
                        instance=self.instance, reverse=self.reverse,
                        model=self.model, pk_set=old_ids)
                # Remove the specified objects from the join table
                db = router.db_for_write(self.through.__class__, instance=self.instance)
                db = router.db_for_write(self.through, instance=self.instance)
                self.through._default_manager.using(db).filter(**{
                    source_field_name: self._pk_val,
                    '%s__in' % target_field_name: old_ids
@@ -621,7 +621,7 @@ def create_many_related_manager(superclass, rel=False):
                signals.m2m_changed.send(sender=rel.through, action="pre_clear",
                    instance=self.instance, reverse=self.reverse,
                    model=self.model, pk_set=None)
            db = router.db_for_write(self.through.__class__, instance=self.instance)
            db = router.db_for_write(self.through, instance=self.instance)
            self.through._default_manager.using(db).filter(**{
                source_field_name: self._pk_val
            }).delete()
+53 −0
Original line number Diff line number Diff line
@@ -1679,3 +1679,56 @@ class PickleQuerySetTestCase(TestCase):
            Book.objects.using(db).create(title='Dive into Python', published=datetime.date(2009, 5, 4))
            qs = Book.objects.all()
            self.assertEqual(qs.db, pickle.loads(pickle.dumps(qs)).db)

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()