Commit c8873bbb authored by Russell Keith-Magee's avatar Russell Keith-Magee
Browse files

Made the database master router tolerant of router definitions that omit...

Made the database master router tolerant of router definitions that omit individual routing methods.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@12304 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent b0d218e9
Loading
Loading
Loading
Loading
+21 −9
Original line number Diff line number Diff line
@@ -103,9 +103,13 @@ class ConnectionRouter(object):
        def _route_db(self, model, **hints):
            chosen_db = None
            for router in self.routers:
                try:
                    chosen_db = getattr(router, action)(model, **hints)
                    if chosen_db:
                        return chosen_db
                except AttributeError:
                    # If the router doesn't have a method, skip to the next one.
                    pass
            try:
                return hints['instance']._state.db or DEFAULT_DB_ALIAS
            except KeyError:
@@ -117,14 +121,22 @@ class ConnectionRouter(object):

    def allow_relation(self, obj1, obj2, **hints):
        for router in self.routers:
            try:
                allow = router.allow_relation(obj1, obj2, **hints)
                if allow is not None:
                    return allow
            except AttributeError:
                # If the router doesn't have a method, skip to the next one.
                pass
        return obj1._state.db == obj2._state.db

    def allow_syncdb(self, db, model):
        for router in self.routers:
            try:
                allow = router.allow_syncdb(db, model)
                if allow is not None:
                    return allow
            except AttributeError:
                # If the router doesn't have a method, skip to the next one.
                pass
        return True
+5 −1
Original line number Diff line number Diff line
@@ -99,7 +99,7 @@ routing scheme.
Database routers
----------------

A database Router is a class that provides four methods:
A database Router is a class that provides up to four methods:

.. method:: db_for_read(model, **hints)

@@ -141,6 +141,10 @@ A database Router is a class that provides four methods:
    the router has no opinion. This method can be used to determine
    the availability of a model on a given database.

A router doesn't have to provide *all* these methods - it omit one or
more of them. If one of the methods is omitted, Django will skip that
router when performing the relevant check.

.. _topics-db-multi-db-hints:

Hints
+36 −0
Original line number Diff line number Diff line
@@ -674,6 +674,11 @@ class AuthRouter(object):
            return False
        return None

class WriteRouter(object):
    # A router that only expresses an opinion on writes
    def db_for_write(self, model, **hints):
        return 'writer'

class RouterTestCase(TestCase):
    multi_db = True

@@ -724,6 +729,37 @@ class RouterTestCase(TestCase):
        self.assertTrue(router.allow_syncdb('other', User))
        self.assertFalse(router.allow_syncdb('other', Book))

    def test_partial_router(self):
        "A router can choose to implement a subset of methods"
        dive = Book.objects.using('other').create(title="Dive into Python",
                                                  published=datetime.date(2009, 5, 4))

        # First check the baseline behaviour

        self.assertEquals(router.db_for_read(User), 'other')
        self.assertEquals(router.db_for_read(Book), 'other')

        self.assertEquals(router.db_for_write(User), 'default')
        self.assertEquals(router.db_for_write(Book), 'default')

        self.assertTrue(router.allow_relation(dive, dive))

        self.assertTrue(router.allow_syncdb('default', User))
        self.assertTrue(router.allow_syncdb('default', Book))

        router.routers = [WriteRouter(), AuthRouter(), TestRouter()]

        self.assertEquals(router.db_for_read(User), 'other')
        self.assertEquals(router.db_for_read(Book), 'other')

        self.assertEquals(router.db_for_write(User), 'writer')
        self.assertEquals(router.db_for_write(Book), 'writer')

        self.assertTrue(router.allow_relation(dive, dive))

        self.assertFalse(router.allow_syncdb('default', User))
        self.assertTrue(router.allow_syncdb('default', Book))


    def test_database_routing(self):
        marty = Person.objects.using('default').create(name="Marty Alchin")