diff --git a/django/contrib/auth/management/__init__.py b/django/contrib/auth/management/__init__.py index e1b9be2e9b..343828ec17 100644 --- a/django/contrib/auth/management/__init__.py +++ b/django/contrib/auth/management/__init__.py @@ -64,7 +64,7 @@ def create_permissions(app, created_models, verbosity, db=DEFAULT_DB_ALIAS, **kw except UnavailableApp: return - if not router.allow_syncdb(db, auth_app.Permission): + if not router.allow_migrate(db, auth_app.Permission): return from django.contrib.contenttypes.models import ContentType diff --git a/django/contrib/contenttypes/management.py b/django/contrib/contenttypes/management.py index 21a34b2bfa..4278bbd1e7 100644 --- a/django/contrib/contenttypes/management.py +++ b/django/contrib/contenttypes/management.py @@ -16,7 +16,7 @@ def update_contenttypes(app, created_models, verbosity=2, db=DEFAULT_DB_ALIAS, * except UnavailableApp: return - if not router.allow_syncdb(db, ContentType): + if not router.allow_migrate(db, ContentType): return ContentType.objects.clear_cache() diff --git a/django/contrib/gis/tests/layermap/tests.py b/django/contrib/gis/tests/layermap/tests.py index c4c27b353e..3b040624f3 100644 --- a/django/contrib/gis/tests/layermap/tests.py +++ b/django/contrib/gis/tests/layermap/tests.py @@ -311,7 +311,7 @@ class OtherRouter(object): def allow_relation(self, obj1, obj2, **hints): return None - def allow_syncdb(self, db, model): + def allow_migrate(self, db, model): return True diff --git a/django/contrib/sites/management.py b/django/contrib/sites/management.py index 3ab49e5482..d9e3a2126c 100644 --- a/django/contrib/sites/management.py +++ b/django/contrib/sites/management.py @@ -11,7 +11,7 @@ from django.core.management.color import no_style def create_default_site(app, created_models, verbosity, db, **kwargs): # Only create the default sites in databases where Django created the table - if Site in created_models and router.allow_syncdb(db, Site) : + if Site in created_models and router.allow_migrate(db, Site) : # The default settings set SITE_ID = 1, and some tests in Django's test # suite rely on this value. However, if database sequences are reused # (e.g. in the test suite after flush/syncdb), it isn't guaranteed that diff --git a/django/core/management/commands/createcachetable.py b/django/core/management/commands/createcachetable.py index d7ce3e93fd..27668f272d 100644 --- a/django/core/management/commands/createcachetable.py +++ b/django/core/management/commands/createcachetable.py @@ -24,7 +24,7 @@ class Command(LabelCommand): def handle_label(self, tablename, **options): db = options.get('database') cache = BaseDatabaseCache(tablename, {}) - if not router.allow_syncdb(db, cache.cache_model_class): + if not router.allow_migrate(db, cache.cache_model_class): return connection = connections[db] fields = ( diff --git a/django/core/management/commands/dumpdata.py b/django/core/management/commands/dumpdata.py index c5eb1b9a9e..5e440196fc 100644 --- a/django/core/management/commands/dumpdata.py +++ b/django/core/management/commands/dumpdata.py @@ -117,7 +117,7 @@ class Command(BaseCommand): for model in sort_dependencies(app_list.items()): if model in excluded_models: continue - if not model._meta.proxy and router.allow_syncdb(using, model): + if not model._meta.proxy and router.allow_migrate(using, model): if use_base_manager: objects = model._base_manager else: diff --git a/django/core/management/commands/flush.py b/django/core/management/commands/flush.py index 2ced3a2d60..a6ea45ce95 100644 --- a/django/core/management/commands/flush.py +++ b/django/core/management/commands/flush.py @@ -96,6 +96,6 @@ Are you sure you want to do this? for app in models.get_apps(): all_models.extend([ m for m in models.get_models(app, include_auto_created=True) - if router.allow_syncdb(database, m) + if router.allow_migrate(database, m) ]) emit_post_migrate_signal(set(all_models), verbosity, interactive, database) diff --git a/django/core/management/commands/loaddata.py b/django/core/management/commands/loaddata.py index 6856e85e45..802226f9d1 100644 --- a/django/core/management/commands/loaddata.py +++ b/django/core/management/commands/loaddata.py @@ -133,7 +133,7 @@ class Command(BaseCommand): for obj in objects: objects_in_fixture += 1 - if router.allow_syncdb(self.using, obj.object.__class__): + if router.allow_migrate(self.using, obj.object.__class__): loaded_objects_in_fixture += 1 self.models.add(obj.object.__class__) try: diff --git a/django/core/management/commands/migrate.py b/django/core/management/commands/migrate.py index cf0e40e6c7..17b5a7dfe9 100644 --- a/django/core/management/commands/migrate.py +++ b/django/core/management/commands/migrate.py @@ -149,7 +149,7 @@ class Command(BaseCommand): (app.__name__.split('.')[-2], [ m for m in models.get_models(app, include_auto_created=True) - if router.allow_syncdb(connection.alias, m) + if router.allow_migrate(connection.alias, m) ]) for app in models.get_apps() if app.__name__.split('.')[-2] in apps ] diff --git a/django/db/backends/__init__.py b/django/db/backends/__init__.py index 80e66b3ad4..7185644cc3 100644 --- a/django/db/backends/__init__.py +++ b/django/db/backends/__init__.py @@ -1243,7 +1243,7 @@ class BaseDatabaseIntrospection(object): for model in models.get_models(app): if not model._meta.managed: continue - if not router.allow_syncdb(self.connection.alias, model): + if not router.allow_migrate(self.connection.alias, model): continue tables.add(model._meta.db_table) tables.update([f.m2m_db_table() for f in model._meta.local_many_to_many]) @@ -1263,7 +1263,7 @@ class BaseDatabaseIntrospection(object): all_models = [] for app in models.get_apps(): for model in models.get_models(app): - if router.allow_syncdb(self.connection.alias, model): + if router.allow_migrate(self.connection.alias, model): all_models.append(model) tables = list(map(self.table_name_converter, tables)) return set([ @@ -1284,7 +1284,7 @@ class BaseDatabaseIntrospection(object): continue if model._meta.swapped: continue - if not router.allow_syncdb(self.connection.alias, model): + if not router.allow_migrate(self.connection.alias, model): continue for f in model._meta.local_fields: if isinstance(f, models.AutoField): diff --git a/django/db/utils.py b/django/db/utils.py index 36b89d9acf..c1bce7326b 100644 --- a/django/db/utils.py +++ b/django/db/utils.py @@ -262,10 +262,13 @@ class ConnectionRouter(object): return allow return obj1._state.db == obj2._state.db - def allow_syncdb(self, db, model): + def allow_migrate(self, db, model): for router in self.routers: try: - method = router.allow_syncdb + try: + method = router.allow_migrate + except AttributeError: + method = router.allow_syncdb except AttributeError: # If the router doesn't have a method, skip to the next one. pass diff --git a/docs/internals/deprecation.txt b/docs/internals/deprecation.txt index 7fb7ec7cad..25d54d5269 100644 --- a/docs/internals/deprecation.txt +++ b/docs/internals/deprecation.txt @@ -414,12 +414,17 @@ these changes. * ``django.utils.unittest`` will be removed. +* The ``syncdb`` command will be removed. + * ``django.db.models.signals.pre_syncdb`` and ``django.db.models.signals.post_syncdb`` will be removed, and ``django.db.models.signals.pre_migrate`` and ``django.db.models.signals.post_migrate`` will lose their ``create_models`` and ``created_models`` arguments. +* ``allow_syncdb`` on database routers will no longer automatically become + ``allow_migrate``. + 2.0 --- diff --git a/docs/releases/1.7.txt b/docs/releases/1.7.txt index 5bd462b4a8..df2b10d18c 100644 --- a/docs/releases/1.7.txt +++ b/docs/releases/1.7.txt @@ -52,7 +52,10 @@ but a few of the key features are: :data:`~django.db.models.signals.post_migrate` respectively. The ``create_models``/``created_models`` argument has also been deprecated. -* Routers something something. +* The ``allow_syncdb`` method on database routers is now called ``allow_migrate``, + but still performs the same function. Routers with ``allow_syncdb`` methods + will still work, but that method name is deprecated and you should change + it as soon as possible (nothing more than renaming is required). Admin shortcuts support time zones ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/topics/cache.txt b/docs/topics/cache.txt index 2352770bad..ea23943c81 100644 --- a/docs/topics/cache.txt +++ b/docs/topics/cache.txt @@ -215,8 +215,8 @@ operations to ``cache_slave``, and all write operations to return 'cache_master' return None - def allow_syncdb(self, db, model): - "Only synchronize the cache model on master" + def allow_migrate(self, db, model): + "Only install the cache model on master" if model._meta.app_label in ('django_cache',): return db == 'cache_master' return None diff --git a/docs/topics/db/multi-db.txt b/docs/topics/db/multi-db.txt index ac329cc4fc..6c74fb944d 100644 --- a/docs/topics/db/multi-db.txt +++ b/docs/topics/db/multi-db.txt @@ -155,14 +155,17 @@ A database Router is a class that provides up to four methods: used by foreign key and many to many operations to determine if a relation should be allowed between two objects. -.. method:: allow_syncdb(db, model) +.. method:: allow_migrate(db, model) - Determine if the ``model`` should be synchronized onto the + Determine if the ``model`` should have tables/indexes created in the database with alias ``db``. Return True if the model should be - synchronized, False if it should not be synchronized, or None if + migrated, False if it should not be migrated, or None if the router has no opinion. This method can be used to determine the availability of a model on a given database. + Note that if this returns ``True`` for an app with migrations but + ``False`` for an app those migrations depend on, Django will error. + A router doesn't have to provide *all* these methods -- it may omit one or more of them. If one of the methods is omitted, Django will skip that router when performing the relevant check. @@ -288,7 +291,7 @@ send queries for the ``auth`` app to ``auth_db``:: return True return None - def allow_syncdb(self, db, model): + def allow_migrate(self, db, model): """ Make sure the auth app only appears in the 'auth_db' database. @@ -328,7 +331,7 @@ from:: return True return None - def allow_syncdb(self, db, model): + def allow_migrate(self, db, model): """ All non-auth models end up in this pool. """ @@ -347,7 +350,7 @@ be queried in the order the are listed in the result, decisions concerning the models in ``auth`` are processed before any other decision is made. If the :setting:`DATABASE_ROUTERS` setting listed the two routers in the other order, -``MasterSlaveRouter.allow_syncdb()`` would be processed first. The +``MasterSlaveRouter.allow_migrate()`` would be processed first. The catch-all nature of the MasterSlaveRouter implementation would mean that all models would be available on all databases. diff --git a/tests/cache/tests.py b/tests/cache/tests.py index bccac6b5a8..5cf199794c 100644 --- a/tests/cache/tests.py +++ b/tests/cache/tests.py @@ -895,7 +895,7 @@ class DBCacheRouter(object): if model._meta.app_label == 'django_cache': return 'other' - def allow_syncdb(self, db, model): + def allow_migrate(self, db, model): if model._meta.app_label == 'django_cache': return db == 'other' diff --git a/tests/multiple_database/tests.py b/tests/multiple_database/tests.py index 12a6379ca0..e65fa4e19d 100644 --- a/tests/multiple_database/tests.py +++ b/tests/multiple_database/tests.py @@ -933,7 +933,7 @@ class TestRouter(object): def allow_relation(self, obj1, obj2, **hints): return obj1._state.db in ('default', 'other') and obj2._state.db in ('default', 'other') - def allow_syncdb(self, db, model): + def allow_migrate(self, db, model): return True class AuthRouter(object): @@ -960,7 +960,7 @@ class AuthRouter(object): return True return None - def allow_syncdb(self, db, model): + def allow_migrate(self, db, model): "Make sure the auth app only appears on the 'other' db" if db == 'other': return model._meta.app_label == 'auth' @@ -1022,30 +1022,30 @@ class RouterTestCase(TestCase): def test_syncdb_selection(self): "Synchronization behavior is predictable" - self.assertTrue(router.allow_syncdb('default', User)) - self.assertTrue(router.allow_syncdb('default', Book)) + self.assertTrue(router.allow_migrate('default', User)) + self.assertTrue(router.allow_migrate('default', Book)) - self.assertTrue(router.allow_syncdb('other', User)) - self.assertTrue(router.allow_syncdb('other', Book)) + self.assertTrue(router.allow_migrate('other', User)) + self.assertTrue(router.allow_migrate('other', Book)) # Add the auth router to the chain. # TestRouter is a universal synchronizer, so it should have no effect. router.routers = [TestRouter(), AuthRouter()] - self.assertTrue(router.allow_syncdb('default', User)) - self.assertTrue(router.allow_syncdb('default', Book)) + self.assertTrue(router.allow_migrate('default', User)) + self.assertTrue(router.allow_migrate('default', Book)) - self.assertTrue(router.allow_syncdb('other', User)) - self.assertTrue(router.allow_syncdb('other', Book)) + self.assertTrue(router.allow_migrate('other', User)) + self.assertTrue(router.allow_migrate('other', Book)) # Now check what happens if the router order is the other way around router.routers = [AuthRouter(), TestRouter()] - self.assertFalse(router.allow_syncdb('default', User)) - self.assertTrue(router.allow_syncdb('default', Book)) + self.assertFalse(router.allow_migrate('default', User)) + self.assertTrue(router.allow_migrate('default', Book)) - self.assertTrue(router.allow_syncdb('other', User)) - self.assertFalse(router.allow_syncdb('other', Book)) + self.assertTrue(router.allow_migrate('other', User)) + self.assertFalse(router.allow_migrate('other', Book)) def test_partial_router(self): "A router can choose to implement a subset of methods" @@ -1062,8 +1062,8 @@ class RouterTestCase(TestCase): self.assertTrue(router.allow_relation(dive, dive)) - self.assertTrue(router.allow_syncdb('default', User)) - self.assertTrue(router.allow_syncdb('default', Book)) + self.assertTrue(router.allow_migrate('default', User)) + self.assertTrue(router.allow_migrate('default', Book)) router.routers = [WriteRouter(), AuthRouter(), TestRouter()] @@ -1075,8 +1075,8 @@ class RouterTestCase(TestCase): self.assertTrue(router.allow_relation(dive, dive)) - self.assertFalse(router.allow_syncdb('default', User)) - self.assertTrue(router.allow_syncdb('default', Book)) + self.assertFalse(router.allow_migrate('default', User)) + self.assertTrue(router.allow_migrate('default', Book)) def test_database_routing(self): @@ -1607,12 +1607,12 @@ class AuthTestCase(TestCase): self.assertEqual(User.objects.using('other').count(), 1) def test_dumpdata(self): - "Check that dumpdata honors allow_syncdb restrictions on the router" + "Check that dumpdata honors allow_migrate restrictions on the router" User.objects.create_user('alice', 'alice@example.com') User.objects.db_manager('default').create_user('bob', 'bob@example.com') # Check that dumping the default database doesn't try to include auth - # because allow_syncdb prohibits auth on default + # because allow_migrate prohibits auth on default new_io = StringIO() management.call_command('dumpdata', 'auth', format='json', database='default', stdout=new_io) command_output = new_io.getvalue().strip() @@ -1625,10 +1625,10 @@ class AuthTestCase(TestCase): self.assertTrue('"email": "alice@example.com"' in command_output) class AntiPetRouter(object): - # A router that only expresses an opinion on syncdb, + # A router that only expresses an opinion on migrate, # passing pets to the 'other' database - def allow_syncdb(self, db, model): + def allow_migrate(self, db, model): "Make sure the auth app only appears on the 'other' db" if db == 'other': return model._meta.object_name == 'Pet' @@ -1917,7 +1917,7 @@ class RouterModelArgumentTestCase(TestCase): class SyncOnlyDefaultDatabaseRouter(object): - def allow_syncdb(self, db, model): + def allow_migrate(self, db, model): return db == DEFAULT_DB_ALIAS