test_multidb.py 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. import unittest
  2. try:
  3. import sqlparse
  4. except ImportError:
  5. sqlparse = None
  6. from django.db import migrations, models, connection
  7. from django.db.migrations.state import ProjectState
  8. from django.test import override_settings
  9. from .test_operations import OperationTestBase
  10. class AgnosticRouter(object):
  11. """
  12. A router that doesn't have an opinion regarding migrating.
  13. """
  14. def allow_migrate(self, db, model, **hints):
  15. return None
  16. class MigrateNothingRouter(object):
  17. """
  18. A router that doesn't allow migrating.
  19. """
  20. def allow_migrate(self, db, model, **hints):
  21. return False
  22. class MigrateEverythingRouter(object):
  23. """
  24. A router that always allows migrating.
  25. """
  26. def allow_migrate(self, db, model, **hints):
  27. return True
  28. class MigrateWhenFooRouter(object):
  29. """
  30. A router that allows migrating depending on a hint.
  31. """
  32. def allow_migrate(self, db, model, **hints):
  33. return hints.get('foo', False)
  34. class MultiDBOperationTests(OperationTestBase):
  35. multi_db = True
  36. def _test_create_model(self, app_label, should_run):
  37. """
  38. Tests that CreateModel honours multi-db settings.
  39. """
  40. operation = migrations.CreateModel(
  41. "Pony",
  42. [("id", models.AutoField(primary_key=True))],
  43. )
  44. # Test the state alteration
  45. project_state = ProjectState()
  46. new_state = project_state.clone()
  47. operation.state_forwards(app_label, new_state)
  48. # Test the database alteration
  49. self.assertTableNotExists("%s_pony" % app_label)
  50. with connection.schema_editor() as editor:
  51. operation.database_forwards(app_label, editor, project_state, new_state)
  52. if should_run:
  53. self.assertTableExists("%s_pony" % app_label)
  54. else:
  55. self.assertTableNotExists("%s_pony" % app_label)
  56. # And test reversal
  57. with connection.schema_editor() as editor:
  58. operation.database_backwards(app_label, editor, new_state, project_state)
  59. self.assertTableNotExists("%s_pony" % app_label)
  60. @override_settings(DATABASE_ROUTERS=[AgnosticRouter()])
  61. def test_create_model(self):
  62. """
  63. Test when router doesn't have an opinion (i.e. CreateModel should run).
  64. """
  65. self._test_create_model("test_mltdb_crmo", should_run=True)
  66. @override_settings(DATABASE_ROUTERS=[MigrateNothingRouter()])
  67. def test_create_model2(self):
  68. """
  69. Test when router returns False (i.e. CreateModel shouldn't run).
  70. """
  71. self._test_create_model("test_mltdb_crmo2", should_run=False)
  72. @override_settings(DATABASE_ROUTERS=[MigrateEverythingRouter()])
  73. def test_create_model3(self):
  74. """
  75. Test when router returns True (i.e. CreateModel should run).
  76. """
  77. self._test_create_model("test_mltdb_crmo3", should_run=True)
  78. def test_create_model4(self):
  79. """
  80. Test multiple routers.
  81. """
  82. with override_settings(DATABASE_ROUTERS=[AgnosticRouter(), AgnosticRouter()]):
  83. self._test_create_model("test_mltdb_crmo4", should_run=True)
  84. with override_settings(DATABASE_ROUTERS=[MigrateNothingRouter(), MigrateEverythingRouter()]):
  85. self._test_create_model("test_mltdb_crmo4", should_run=False)
  86. with override_settings(DATABASE_ROUTERS=[MigrateEverythingRouter(), MigrateNothingRouter()]):
  87. self._test_create_model("test_mltdb_crmo4", should_run=True)
  88. def _test_run_sql(self, app_label, should_run, hints=None):
  89. with override_settings(DATABASE_ROUTERS=[MigrateEverythingRouter()]):
  90. project_state = self.set_up_test_model(app_label)
  91. sql = """
  92. INSERT INTO {0}_pony (pink, weight) VALUES (1, 3.55);
  93. INSERT INTO {0}_pony (pink, weight) VALUES (3, 5.0);
  94. """.format(app_label)
  95. operation = migrations.RunSQL(sql, hints=hints or {})
  96. # Test the state alteration does nothing
  97. new_state = project_state.clone()
  98. operation.state_forwards(app_label, new_state)
  99. self.assertEqual(new_state, project_state)
  100. # Test the database alteration
  101. self.assertEqual(project_state.apps.get_model(app_label, "Pony").objects.count(), 0)
  102. with connection.schema_editor() as editor:
  103. operation.database_forwards(app_label, editor, project_state, new_state)
  104. Pony = project_state.apps.get_model(app_label, "Pony")
  105. if should_run:
  106. self.assertEqual(Pony.objects.count(), 2)
  107. else:
  108. self.assertEqual(Pony.objects.count(), 0)
  109. @unittest.skipIf(sqlparse is None and connection.features.requires_sqlparse_for_splitting, "Missing sqlparse")
  110. @override_settings(DATABASE_ROUTERS=[MigrateNothingRouter()])
  111. def test_run_sql(self):
  112. self._test_run_sql("test_mltdb_runsql", should_run=False)
  113. @unittest.skipIf(sqlparse is None and connection.features.requires_sqlparse_for_splitting, "Missing sqlparse")
  114. @override_settings(DATABASE_ROUTERS=[MigrateWhenFooRouter()])
  115. def test_run_sql2(self):
  116. self._test_run_sql("test_mltdb_runsql2", should_run=False)
  117. self._test_run_sql("test_mltdb_runsql2", should_run=True, hints={'foo': True})
  118. def _test_run_python(self, app_label, should_run, hints=None):
  119. with override_settings(DATABASE_ROUTERS=[MigrateEverythingRouter()]):
  120. project_state = self.set_up_test_model(app_label)
  121. # Create the operation
  122. def inner_method(models, schema_editor):
  123. Pony = models.get_model(app_label, "Pony")
  124. Pony.objects.create(pink=1, weight=3.55)
  125. Pony.objects.create(weight=5)
  126. operation = migrations.RunPython(inner_method, hints=hints or {})
  127. # Test the state alteration does nothing
  128. new_state = project_state.clone()
  129. operation.state_forwards(app_label, new_state)
  130. self.assertEqual(new_state, project_state)
  131. # Test the database alteration
  132. self.assertEqual(project_state.apps.get_model(app_label, "Pony").objects.count(), 0)
  133. with connection.schema_editor() as editor:
  134. operation.database_forwards(app_label, editor, project_state, new_state)
  135. Pony = project_state.apps.get_model(app_label, "Pony")
  136. if should_run:
  137. self.assertEqual(Pony.objects.count(), 2)
  138. else:
  139. self.assertEqual(Pony.objects.count(), 0)
  140. @override_settings(DATABASE_ROUTERS=[MigrateNothingRouter()])
  141. def test_run_python(self):
  142. self._test_run_python("test_mltdb_runpython", should_run=False)
  143. @override_settings(DATABASE_ROUTERS=[MigrateWhenFooRouter()])
  144. def test_run_python2(self):
  145. self._test_run_python("test_mltdb_runpython2", should_run=False)
  146. self._test_run_python("test_mltdb_runpython2", should_run=True, hints={'foo': True})