mirror of
				https://github.com/django/django.git
				synced 2025-11-03 21:25:09 +00:00 
			
		
		
		
	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
This commit is contained in:
		
							parent
							
								
									b0d218e9e2
								
							
						
					
					
						commit
						c8873bbba7
					
				
					 3 changed files with 62 additions and 10 deletions
				
			
		| 
						 | 
				
			
			@ -103,9 +103,13 @@ class ConnectionRouter(object):
 | 
			
		|||
        def _route_db(self, model, **hints):
 | 
			
		||||
            chosen_db = None
 | 
			
		||||
            for router in self.routers:
 | 
			
		||||
                chosen_db = getattr(router, action)(model, **hints)
 | 
			
		||||
                if chosen_db:
 | 
			
		||||
                    return chosen_db
 | 
			
		||||
                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:
 | 
			
		||||
            allow = router.allow_relation(obj1, obj2, **hints)
 | 
			
		||||
            if allow is not None:
 | 
			
		||||
                return allow
 | 
			
		||||
            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:
 | 
			
		||||
            allow = router.allow_syncdb(db, model)
 | 
			
		||||
            if allow is not None:
 | 
			
		||||
                return allow
 | 
			
		||||
            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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue