test_multidb.py 6.4 KB

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