django-postpone-index 0.0.3__tar.gz → 0.0.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. {django_postpone_index-0.0.3/django_postpone_index.egg-info → django_postpone_index-0.0.4}/PKG-INFO +2 -1
  2. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/README.md +1 -0
  3. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/config/base_tests.py +28 -5
  4. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/config/settings.py +2 -0
  5. django_postpone_index-0.0.4/dev/test_explicit_constraint/tests.py +54 -0
  6. {django_postpone_index-0.0.3/dev/test_gis_index → django_postpone_index-0.0.4/dev/test_explicit_index}/tests.py +0 -1
  7. django_postpone_index-0.0.4/dev/test_fields/tests.py +43 -0
  8. django_postpone_index-0.0.4/dev/test_fields_rename/migrations/0001_initial.py +72 -0
  9. django_postpone_index-0.0.4/dev/test_fields_rename/migrations/0002_auto_20260204_0917.py +87 -0
  10. django_postpone_index-0.0.4/dev/test_fields_rename/models.py +81 -0
  11. {django_postpone_index-0.0.3/dev/test_fields → django_postpone_index-0.0.4/dev/test_fields_rename}/tests.py +0 -1
  12. {django_postpone_index-0.0.3/dev/test_explicit_constraint → django_postpone_index-0.0.4/dev/test_gis_index}/tests.py +0 -1
  13. {django_postpone_index-0.0.3/dev/test_explicit_index → django_postpone_index-0.0.4/dev/test_index_together}/tests.py +0 -1
  14. django_postpone_index-0.0.4/dev/test_model_rename/migrations/0001_initial.py +72 -0
  15. django_postpone_index-0.0.4/dev/test_model_rename/migrations/0002_auto_20260204_1037.py +38 -0
  16. django_postpone_index-0.0.4/dev/test_model_rename/models.py +60 -0
  17. django_postpone_index-0.0.4/dev/test_model_rename/tests.py +9 -0
  18. django_postpone_index-0.0.4/dev/test_unique_together/tests.py +72 -0
  19. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4/django_postpone_index.egg-info}/PKG-INFO +2 -1
  20. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/django_postpone_index.egg-info/SOURCES.txt +12 -0
  21. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/postpone_index/_version.py +3 -3
  22. django_postpone_index-0.0.4/postpone_index/contrib/postgis/__init__.py +0 -0
  23. django_postpone_index-0.0.4/postpone_index/contrib/postgres/__init__.py +0 -0
  24. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/postpone_index/contrib/postgres/schema.py +32 -1
  25. django_postpone_index-0.0.4/postpone_index/management/__init__.py +0 -0
  26. django_postpone_index-0.0.4/postpone_index/management/commands/__init__.py +0 -0
  27. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/postpone_index/models.py +2 -1
  28. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/postpone_index/utils.py +23 -5
  29. django_postpone_index-0.0.3/dev/test_index_together/tests.py +0 -10
  30. django_postpone_index-0.0.3/dev/test_unique_together/tests.py +0 -10
  31. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/.github/workflows/ci.yml +0 -0
  32. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/.gitignore +0 -0
  33. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/config/__init__.py +0 -0
  34. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/config/urls.py +0 -0
  35. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/config/utils.py +0 -0
  36. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/config/wsgi.py +0 -0
  37. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/manage.py +0 -0
  38. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_explicit_constraint/__init__.py +0 -0
  39. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_explicit_constraint/migrations/0001_initial.py +0 -0
  40. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_explicit_constraint/migrations/0002_auto_20260130_1044.py +0 -0
  41. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_explicit_constraint/migrations/0003_auto_20260130_1052.py +0 -0
  42. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_explicit_constraint/migrations/__init__.py +0 -0
  43. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_explicit_constraint/models.py +0 -0
  44. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_explicit_index/__init__.py +0 -0
  45. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_explicit_index/migrations/0001_initial.py +0 -0
  46. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_explicit_index/migrations/0002_auto_20260130_1044.py +0 -0
  47. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_explicit_index/migrations/0003_auto_20260130_1052.py +0 -0
  48. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_explicit_index/migrations/__init__.py +0 -0
  49. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_explicit_index/models.py +0 -0
  50. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_fields/__init__.py +0 -0
  51. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_fields/migrations/0001_initial.py +0 -0
  52. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_fields/migrations/0002_auto_20260130_1258.py +0 -0
  53. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_fields/migrations/0003_auto_20260130_1259.py +0 -0
  54. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_fields/migrations/__init__.py +0 -0
  55. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_fields/models.py +0 -0
  56. {django_postpone_index-0.0.3/dev/test_gis_index → django_postpone_index-0.0.4/dev/test_fields_rename}/__init__.py +0 -0
  57. {django_postpone_index-0.0.3/dev/test_gis_index → django_postpone_index-0.0.4/dev/test_fields_rename}/migrations/__init__.py +0 -0
  58. {django_postpone_index-0.0.3/dev/test_ignore_migration → django_postpone_index-0.0.4/dev/test_gis_index}/__init__.py +0 -0
  59. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_gis_index/migrations/0001_initial.py +0 -0
  60. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_gis_index/migrations/0002_gisindex1_mline.py +0 -0
  61. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_gis_index/migrations/0003_auto_20260202_1156.py +0 -0
  62. {django_postpone_index-0.0.3/dev/test_ignore_migration → django_postpone_index-0.0.4/dev/test_gis_index}/migrations/__init__.py +0 -0
  63. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_gis_index/models.py +0 -0
  64. {django_postpone_index-0.0.3/dev/test_index_together → django_postpone_index-0.0.4/dev/test_ignore_migration}/__init__.py +0 -0
  65. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_ignore_migration/migrations/0001_initial.py +0 -0
  66. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_ignore_migration/migrations/0002_auto_20260130_1044.py +0 -0
  67. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_ignore_migration/migrations/0003_auto_20260130_1052.py +0 -0
  68. {django_postpone_index-0.0.3/dev/test_index_together → django_postpone_index-0.0.4/dev/test_ignore_migration}/migrations/__init__.py +0 -0
  69. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_ignore_migration/models.py +0 -0
  70. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_ignore_migration/tests.py +0 -0
  71. {django_postpone_index-0.0.3/dev/test_unique_together → django_postpone_index-0.0.4/dev/test_index_together}/__init__.py +0 -0
  72. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_index_together/migrations/0001_initial.py +0 -0
  73. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_index_together/migrations/0002_auto_20260130_1044.py +0 -0
  74. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_index_together/migrations/0003_auto_20260130_1053.py +0 -0
  75. {django_postpone_index-0.0.3/dev/test_unique_together → django_postpone_index-0.0.4/dev/test_index_together}/migrations/__init__.py +0 -0
  76. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_index_together/models.py +0 -0
  77. {django_postpone_index-0.0.3/postpone_index/contrib → django_postpone_index-0.0.4/dev/test_model_rename}/__init__.py +0 -0
  78. {django_postpone_index-0.0.3/postpone_index/contrib/postgis → django_postpone_index-0.0.4/dev/test_model_rename/migrations}/__init__.py +0 -0
  79. {django_postpone_index-0.0.3/postpone_index/contrib/postgres → django_postpone_index-0.0.4/dev/test_unique_together}/__init__.py +0 -0
  80. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_unique_together/migrations/0001_initial.py +0 -0
  81. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_unique_together/migrations/0002_auto_20260130_1044.py +0 -0
  82. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_unique_together/migrations/0003_auto_20260130_1053.py +0 -0
  83. {django_postpone_index-0.0.3/postpone_index/management → django_postpone_index-0.0.4/dev/test_unique_together/migrations}/__init__.py +0 -0
  84. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/dev/test_unique_together/models.py +0 -0
  85. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/django_postpone_index.egg-info/dependency_links.txt +0 -0
  86. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/django_postpone_index.egg-info/requires.txt +0 -0
  87. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/django_postpone_index.egg-info/top_level.txt +0 -0
  88. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/postpone_index/__init__.py +0 -0
  89. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/postpone_index/admin.py +0 -0
  90. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/postpone_index/apps.py +0 -0
  91. {django_postpone_index-0.0.3/postpone_index/management/commands → django_postpone_index-0.0.4/postpone_index/contrib}/__init__.py +0 -0
  92. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/postpone_index/contrib/postgis/base.py +0 -0
  93. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/postpone_index/contrib/postgis/schema.py +0 -0
  94. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/postpone_index/contrib/postgres/base.py +0 -0
  95. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/postpone_index/management/commands/apply_postponed.py +0 -0
  96. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/postpone_index/migration_utils.py +0 -0
  97. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/postpone_index/sql/start.sql +0 -0
  98. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/postpone_index/testing_utils.py +0 -0
  99. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/pyproject.toml +0 -0
  100. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/setup.cfg +0 -0
  101. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/setup.py +0 -0
  102. {django_postpone_index-0.0.3 → django_postpone_index-0.0.4}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-postpone-index
3
- Version: 0.0.3
3
+ Version: 0.0.4
4
4
  Summary: Postpone index creation to provide Zero Downtime Migration feature
5
5
  Home-page: https://github.com/nnseva/django-postpone-index
6
6
  Author: Vsevolod Novikov
@@ -105,6 +105,7 @@ The following complex use cases are processed by the package.
105
105
  - Back Migration. The both, forward and backward migrations are processed.
106
106
  - Implicit index drop while removing the table. The Django doesn't issue a separate SQL to drop indexes of the dropped table.
107
107
  - Implicit index drop while removing the field. The Django doesn't issue a separate SQL to drop indexes related to the dropped column.
108
+ - Rename field (column) name or model (table) name
108
109
 
109
110
  ## Using
110
111
 
@@ -56,6 +56,7 @@ The following complex use cases are processed by the package.
56
56
  - Back Migration. The both, forward and backward migrations are processed.
57
57
  - Implicit index drop while removing the table. The Django doesn't issue a separate SQL to drop indexes of the dropped table.
58
58
  - Implicit index drop while removing the field. The Django doesn't issue a separate SQL to drop indexes related to the dropped column.
59
+ - Rename field (column) name or model (table) name
59
60
 
60
61
  ## Using
61
62
 
@@ -2,19 +2,37 @@
2
2
 
3
3
  from django.apps import apps
4
4
  from django.core.management import call_command
5
- from django.db import DEFAULT_DB_ALIAS, connections
5
+ from django.db import DEFAULT_DB_ALIAS, connection, connections
6
+ from django.db.migrations.loader import MigrationLoader
6
7
  from django.test import override_settings
7
8
 
8
9
  from postpone_index import testing_utils
9
10
 
10
11
 
12
+ def _list_migrations(app_name):
13
+ """Lists all module migrations"""
14
+
15
+ loader = MigrationLoader(connection, ignore_no_migrations=True)
16
+ graph = loader.graph
17
+ ret = []
18
+ for node in graph.leaf_nodes(app_name):
19
+ for plan_node in graph.forwards_plan(node):
20
+ if plan_node[0] == app_name:
21
+ ret.append(plan_node[1])
22
+ return ret
23
+
24
+
11
25
  class TestCase(testing_utils.TestCase):
12
26
  __doc__ = __doc__
13
27
 
14
28
  maxDiff = None
15
29
 
16
30
  module_name = None # Replace in child to the name of the module to test
17
- migrations = None # Replace in child to the list of migrations to test
31
+
32
+ @property
33
+ def migrations(self):
34
+ """All module migrations"""
35
+ return _list_migrations(self.module_name)
18
36
 
19
37
  @classmethod
20
38
  def setUpClass(cls):
@@ -71,14 +89,18 @@ class TestCase(testing_utils.TestCase):
71
89
  def test_002_migrate_equaliry(self):
72
90
  """Test and compare migrations with and without postpone index using introspection"""
73
91
 
92
+ # Baseline: default settings (tests run with POSTPONE_INDEX_IGNORE=True).
93
+ call_command('migrate', self.module_name, 'zero')
94
+
95
+ migration_before = 'zero'
96
+
74
97
  for migration_id in self.migrations:
75
- # Baseline: default settings (tests run with POSTPONE_INDEX_IGNORE=True).
76
- call_command('migrate', self.module_name, 'zero')
98
+ # Store introspection
77
99
  call_command('migrate', self.module_name, migration_id)
78
100
  baseline = self.introspect_app_schema(self.module_name)
101
+ call_command('migrate', self.module_name, migration_before)
79
102
 
80
103
  # With postpone_index enabled.
81
- call_command('migrate', self.module_name, 'zero')
82
104
  with override_settings(POSTPONE_INDEX_IGNORE=False):
83
105
  call_command('migrate', self.module_name, migration_id)
84
106
  call_command('apply_postponed', 'run', '-x')
@@ -93,6 +115,7 @@ class TestCase(testing_utils.TestCase):
93
115
  migration_id,
94
116
  ),
95
117
  )
118
+ migration_before = migration_id
96
119
 
97
120
  @staticmethod
98
121
  def _field_info_to_dict(field_info):
@@ -38,6 +38,8 @@ INSTALLED_APPS = [
38
38
  'config',
39
39
  'test_unique_together',
40
40
  'test_fields',
41
+ 'test_fields_rename',
42
+ 'test_model_rename',
41
43
  'test_explicit_constraint',
42
44
  'test_explicit_index',
43
45
  'test_ignore_migration',
@@ -0,0 +1,54 @@
1
+ """Module Tests"""
2
+
3
+ from config import base_tests
4
+
5
+ from django.core.management import call_command
6
+ from django.db import IntegrityError
7
+ from django.test import override_settings
8
+
9
+
10
+ class ModuleTest(base_tests.TestCase):
11
+ __doc__ = __doc__
12
+
13
+ module_name = __name__.split('.')[0]
14
+
15
+ def test_004_migrate_with_bad_unique_data(self):
16
+ """Test migrations step by step"""
17
+ with override_settings(
18
+ POSTPONE_INDEX_IGNORE=True
19
+ ):
20
+ call_command('migrate', self.module_name, 'zero')
21
+ with override_settings(
22
+ POSTPONE_INDEX_IGNORE=False
23
+ ):
24
+ call_command('migrate', self.module_name, '0002')
25
+
26
+ from test_explicit_constraint.models import ExplicitConstraint1
27
+
28
+ # Duplicate field1/field2/field3 - ok without apply_postponed
29
+ ExplicitConstraint1.objects.create(field1='qwerty', field2='uiop', field3='asdfg')
30
+ duplicate = ExplicitConstraint1.objects.create(field1='qwerty', field2='uiop', field3='asdfg')
31
+
32
+ with self.assertRaises(IntegrityError):
33
+ # Generates error on duplicate records
34
+ call_command('apply_postponed', 'run', '-x')
35
+ duplicate.delete() # remove duplicate
36
+
37
+ call_command('apply_postponed', 'run', '-x') # Now it should be OK
38
+ call_command('apply_postponed', 'cleanup')
39
+ self._assert_postponed_sql_empty()
40
+
41
+ call_command('migrate', self.module_name, '0003')
42
+
43
+ # Duplicate field1/field2/field3 - ok
44
+ # after the migration deleted old unique and not yet created a new one
45
+ duplicate = ExplicitConstraint1.objects.create(field1='qwerty', field2='uiop', field3='asdfg')
46
+
47
+ with self.assertRaises(IntegrityError):
48
+ # Generates error on duplicate records
49
+ call_command('apply_postponed', 'run', '-x')
50
+ duplicate.delete() # remove duplicate
51
+
52
+ call_command('apply_postponed', 'run', '-x') # Now it should be OK
53
+ call_command('apply_postponed', 'cleanup')
54
+ self._assert_postponed_sql_empty()
@@ -7,4 +7,3 @@ class ModuleTest(base_tests.TestCase):
7
7
  __doc__ = __doc__
8
8
 
9
9
  module_name = __name__.split('.')[0]
10
- migrations = ('0001', '0002', '0003')
@@ -0,0 +1,43 @@
1
+ """Module Tests"""
2
+
3
+ from config import base_tests
4
+
5
+ from django.core.management import call_command
6
+ from django.db import IntegrityError
7
+ from django.test import override_settings
8
+
9
+
10
+ class ModuleTest(base_tests.TestCase):
11
+ __doc__ = __doc__
12
+
13
+ module_name = __name__.split('.')[0]
14
+
15
+ def test_004_migrate_with_bad_unique_data(self):
16
+ """Test migrations step by step"""
17
+ with override_settings(
18
+ POSTPONE_INDEX_IGNORE=True
19
+ ):
20
+ call_command('migrate', self.module_name, 'zero')
21
+ with override_settings(
22
+ POSTPONE_INDEX_IGNORE=False
23
+ ):
24
+ call_command('migrate', self.module_name, '0002')
25
+ call_command('apply_postponed', 'run', '-x')
26
+ call_command('apply_postponed', 'cleanup')
27
+ self._assert_postponed_sql_empty()
28
+
29
+ from test_fields.models import UniqueField1
30
+
31
+ # Duplicate field1
32
+ UniqueField1.objects.create(field1='qwerty')
33
+ duplicate = UniqueField1.objects.create(field1='qwerty')
34
+
35
+ call_command('migrate', self.module_name, '0003') # should be OK
36
+ with self.assertRaises(IntegrityError):
37
+ # Generates error on duplicate records
38
+ call_command('apply_postponed', 'run', '-x')
39
+ duplicate.delete() # remove duplicate
40
+
41
+ call_command('apply_postponed', 'run', '-x') # Now it should be OK
42
+ call_command('apply_postponed', 'cleanup')
43
+ self._assert_postponed_sql_empty()
@@ -0,0 +1,72 @@
1
+ # Generated by Django 2.2 on 2026-02-04 09:15
2
+
3
+ import django
4
+ from django.db import migrations, models
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ initial = True
10
+
11
+ dependencies = [
12
+ ]
13
+
14
+ operations = [
15
+ migrations.CreateModel(
16
+ name='ExplicitConstraint1',
17
+ fields=[
18
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
19
+ ('field1', models.CharField(max_length=10)),
20
+ ('field2', models.CharField(max_length=10)),
21
+ ],
22
+ ),
23
+ migrations.CreateModel(
24
+ name='ExplicitIndex1',
25
+ fields=[
26
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
27
+ ('field1', models.CharField(max_length=10)),
28
+ ('field2', models.CharField(max_length=10)),
29
+ ],
30
+ ),
31
+ migrations.CreateModel(
32
+ name='UniqueField1',
33
+ fields=[
34
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
35
+ ('field1', models.CharField(max_length=10, unique=True)),
36
+ ],
37
+ ),
38
+ migrations.CreateModel(
39
+ name='UniqueTogether1',
40
+ fields=[
41
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
42
+ ('field1', models.CharField(max_length=10)),
43
+ ('field2', models.CharField(max_length=10)),
44
+ ],
45
+ options={
46
+ 'unique_together': {('field1', 'field2')},
47
+ },
48
+ ),
49
+ migrations.AddIndex(
50
+ model_name='explicitindex1',
51
+ index=models.Index(fields=['field1', 'field2'], name='explicit_rename_index1_index'),
52
+ ),
53
+ migrations.AddConstraint(
54
+ model_name='explicitconstraint1',
55
+ constraint=models.UniqueConstraint(condition=models.Q(('field1', '<empty>'), ('field2', '<empty>'), _negated=True), fields=('field1', 'field2'), name='explicit_rename_constraint1_non_empty'),
56
+ ),
57
+ ]
58
+
59
+ if django.VERSION < (5, 1):
60
+ operations += [
61
+ migrations.CreateModel(
62
+ name='IndexTogether1',
63
+ fields=[
64
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
65
+ ('field1', models.CharField(max_length=10)),
66
+ ('field2', models.CharField(max_length=10)),
67
+ ],
68
+ options={
69
+ 'index_together': {('field1', 'field2')},
70
+ },
71
+ ),
72
+ ]
@@ -0,0 +1,87 @@
1
+ # Generated by Django 2.2 on 2026-02-04 09:17
2
+
3
+ import django
4
+ from django.db import migrations, models
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ dependencies = [
10
+ ('test_fields_rename', '0001_initial'),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.RemoveConstraint(
15
+ model_name='explicitconstraint1',
16
+ name='explicit_rename_constraint1_non_empty',
17
+ ),
18
+ migrations.RemoveIndex(
19
+ model_name='explicitindex1',
20
+ name='explicit_rename_index1_index',
21
+ ),
22
+ migrations.RenameField(
23
+ model_name='explicitconstraint1',
24
+ old_name='field1',
25
+ new_name='renamed_field1',
26
+ ),
27
+ migrations.RenameField(
28
+ model_name='explicitconstraint1',
29
+ old_name='field2',
30
+ new_name='renamed_field2',
31
+ ),
32
+ migrations.RenameField(
33
+ model_name='explicitindex1',
34
+ old_name='field1',
35
+ new_name='renamed_field1',
36
+ ),
37
+ migrations.RenameField(
38
+ model_name='explicitindex1',
39
+ old_name='field2',
40
+ new_name='renamed_field2',
41
+ ),
42
+ migrations.RenameField(
43
+ model_name='uniquefield1',
44
+ old_name='field1',
45
+ new_name='renamed_field1',
46
+ ),
47
+ migrations.RenameField(
48
+ model_name='uniquetogether1',
49
+ old_name='field1',
50
+ new_name='renamed_field1',
51
+ ),
52
+ migrations.RenameField(
53
+ model_name='uniquetogether1',
54
+ old_name='field2',
55
+ new_name='renamed_field2',
56
+ ),
57
+ migrations.AlterUniqueTogether(
58
+ name='uniquetogether1',
59
+ unique_together={('renamed_field1', 'renamed_field2')},
60
+ ),
61
+ migrations.AddIndex(
62
+ model_name='explicitindex1',
63
+ index=models.Index(fields=['renamed_field1', 'renamed_field2'], name='explicit_rename_index1_index'),
64
+ ),
65
+ migrations.AddConstraint(
66
+ model_name='explicitconstraint1',
67
+ constraint=models.UniqueConstraint(condition=models.Q(('renamed_field1', '<empty>'), ('renamed_field2', '<empty>'), _negated=True), fields=('renamed_field1', 'renamed_field2'), name='explicit_rename_constraint1_non_empty'),
68
+ ),
69
+ ]
70
+
71
+ if django.VERSION < (5, 1):
72
+ operations += [
73
+ migrations.RenameField(
74
+ model_name='indextogether1',
75
+ old_name='field1',
76
+ new_name='renamed_field1',
77
+ ),
78
+ migrations.RenameField(
79
+ model_name='indextogether1',
80
+ old_name='field2',
81
+ new_name='renamed_field2',
82
+ ),
83
+ migrations.AlterIndexTogether(
84
+ name='indextogether1',
85
+ index_together={('renamed_field1', 'renamed_field2')},
86
+ ),
87
+ ]
@@ -0,0 +1,81 @@
1
+ import django
2
+ from django.db import models
3
+
4
+
5
+ class UniqueField1(models.Model):
6
+ """Sequential migrations with unique field"""
7
+
8
+ # Changing history
9
+ # field1 = models.CharField(max_length=10, unique=True) # 0001
10
+ renamed_field1 = models.CharField(max_length=10, unique=True) # 0002
11
+
12
+
13
+ class UniqueTogether1(models.Model):
14
+ """Sequential migrations with unique-together fields"""
15
+
16
+ # Changing history
17
+ # field1 = models.CharField(max_length=10) # 0001
18
+ # field2 = models.CharField(max_length=10) # 0001
19
+ renamed_field1 = models.CharField(max_length=10) # 0002
20
+ renamed_field2 = models.CharField(max_length=10) # 0002
21
+
22
+ class Meta:
23
+ # unique_together = (('field1', 'field2'),)
24
+ unique_together = (('renamed_field1', 'renamed_field2'),)
25
+
26
+
27
+ if django.VERSION < (5, 1):
28
+ class IndexTogether1(models.Model):
29
+ """Sequential migrations with index-together fields"""
30
+
31
+ # Changing history
32
+ # field1 = models.CharField(max_length=10) # 0001
33
+ # field2 = models.CharField(max_length=10) # 0001
34
+ renamed_field1 = models.CharField(max_length=10) # 0002
35
+ renamed_field2 = models.CharField(max_length=10) # 0002
36
+
37
+ class Meta:
38
+ # index_together = (('field1', 'field2'),) # 0001
39
+ index_together = (('renamed_field1', 'renamed_field2'),) # 0002
40
+
41
+
42
+ class ExplicitConstraint1(models.Model):
43
+ """Sequential migrations with explicit named constraint in Meta"""
44
+
45
+ # Changing history
46
+ # field1 = models.CharField(max_length=10) # 0001
47
+ # field2 = models.CharField(max_length=10) # 0001
48
+ renamed_field1 = models.CharField(max_length=10) # 0002
49
+ renamed_field2 = models.CharField(max_length=10) # 0002
50
+
51
+ class Meta:
52
+ # 0001
53
+ # constraints = [
54
+ # models.UniqueConstraint(
55
+ # fields=['field1', 'field2'],
56
+ # condition=~(models.Q(field1='<empty>') & models.Q(field2='<empty>')),
57
+ # name='explicit_rename_constraint1_non_empty'
58
+ # )
59
+ # ]
60
+ # 0002
61
+ constraints = [
62
+ models.UniqueConstraint(
63
+ fields=['renamed_field1', 'renamed_field2'],
64
+ condition=~(models.Q(renamed_field1='<empty>') & models.Q(renamed_field2='<empty>')),
65
+ name='explicit_rename_constraint1_non_empty'
66
+ )
67
+ ]
68
+
69
+
70
+ class ExplicitIndex1(models.Model):
71
+ """Sequential migrations with explicit named index in Meta"""
72
+
73
+ # field1 = models.CharField(max_length=10) # 0001
74
+ # field2 = models.CharField(max_length=10) # 0001
75
+ renamed_field1 = models.CharField(max_length=10) # 0002
76
+ renamed_field2 = models.CharField(max_length=10) # 0002
77
+
78
+ class Meta:
79
+ """Modified Meta"""
80
+ # indexes = [models.Index(fields=['field1', 'field2'], name='explicit_rename_index1_index')] # 0001
81
+ indexes = [models.Index(fields=['renamed_field1', 'renamed_field2'], name='explicit_rename_index1_index')] # 0002
@@ -7,4 +7,3 @@ class ModuleTest(base_tests.TestCase):
7
7
  __doc__ = __doc__
8
8
 
9
9
  module_name = __name__.split('.')[0]
10
- migrations = ('0001', '0002', '0003')
@@ -7,4 +7,3 @@ class ModuleTest(base_tests.TestCase):
7
7
  __doc__ = __doc__
8
8
 
9
9
  module_name = __name__.split('.')[0]
10
- migrations = ('0001', '0002', '0003')
@@ -7,4 +7,3 @@ class ModuleTest(base_tests.TestCase):
7
7
  __doc__ = __doc__
8
8
 
9
9
  module_name = __name__.split('.')[0]
10
- migrations = ('0001', '0002', '0003')
@@ -0,0 +1,72 @@
1
+ # Generated by Django 2.2 on 2026-02-04 10:34
2
+
3
+ import django
4
+ from django.db import migrations, models
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ initial = True
10
+
11
+ dependencies = [
12
+ ]
13
+
14
+ operations = [
15
+ migrations.CreateModel(
16
+ name='ExplicitConstraint1',
17
+ fields=[
18
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
19
+ ('field1', models.CharField(max_length=10)),
20
+ ('field2', models.CharField(max_length=10)),
21
+ ],
22
+ ),
23
+ migrations.CreateModel(
24
+ name='ExplicitIndex1',
25
+ fields=[
26
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
27
+ ('field1', models.CharField(max_length=10)),
28
+ ('field2', models.CharField(max_length=10)),
29
+ ],
30
+ ),
31
+ migrations.CreateModel(
32
+ name='UniqueField1',
33
+ fields=[
34
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
35
+ ('field1', models.CharField(max_length=10, unique=True)),
36
+ ],
37
+ ),
38
+ migrations.CreateModel(
39
+ name='UniqueTogether1',
40
+ fields=[
41
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
42
+ ('field1', models.CharField(max_length=10)),
43
+ ('field2', models.CharField(max_length=10)),
44
+ ],
45
+ options={
46
+ 'unique_together': {('field1', 'field2')},
47
+ },
48
+ ),
49
+ migrations.AddIndex(
50
+ model_name='explicitindex1',
51
+ index=models.Index(fields=['field1', 'field2'], name='explicit_model_index1_index'),
52
+ ),
53
+ migrations.AddConstraint(
54
+ model_name='explicitconstraint1',
55
+ constraint=models.UniqueConstraint(condition=models.Q(('field1', '<empty>'), ('field2', '<empty>'), _negated=True), fields=('field1', 'field2'), name='explicit_model_constraint1_non_empty'),
56
+ ),
57
+ ]
58
+
59
+ if django.VERSION < (5, 1):
60
+ operations += [
61
+ migrations.CreateModel(
62
+ name='IndexTogether1',
63
+ fields=[
64
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
65
+ ('field1', models.CharField(max_length=10)),
66
+ ('field2', models.CharField(max_length=10)),
67
+ ],
68
+ options={
69
+ 'index_together': {('field1', 'field2')},
70
+ },
71
+ ),
72
+ ]
@@ -0,0 +1,38 @@
1
+ # Generated by Django 2.2 on 2026-02-04 10:37
2
+
3
+ import django
4
+ from django.db import migrations, models
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ dependencies = [
10
+ ('test_model_rename', '0001_initial'),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.RenameModel(
15
+ old_name='ExplicitIndex1',
16
+ new_name='ExplicitIndex1Renamed',
17
+ ),
18
+ migrations.RenameModel(
19
+ old_name='ExplicitConstraint1',
20
+ new_name='ExplicitConstraint1Renamed',
21
+ ),
22
+ migrations.RenameModel(
23
+ old_name='UniqueField1',
24
+ new_name='UniqueField1Renamed',
25
+ ),
26
+ migrations.RenameModel(
27
+ old_name='UniqueTogether1',
28
+ new_name='UniqueTogether1Renamed',
29
+ ),
30
+ ]
31
+
32
+ if django.VERSION < (5, 1):
33
+ operations += [
34
+ migrations.RenameModel(
35
+ old_name='IndexTogether1',
36
+ new_name='IndexTogether1Renamed',
37
+ ),
38
+ ]
@@ -0,0 +1,60 @@
1
+ import django
2
+ from django.db import models
3
+
4
+
5
+ # class UniqueField1(models.Model): # 0001
6
+ class UniqueField1Renamed(models.Model): # 0002
7
+ """Sequential migrations with unique field"""
8
+
9
+ field1 = models.CharField(max_length=10, unique=True)
10
+
11
+
12
+ # class UniqueTogether1(models.Model): # 0001
13
+ class UniqueTogether1Renamed(models.Model): # 0002
14
+ """Sequential migrations with unique-together fields"""
15
+
16
+ field1 = models.CharField(max_length=10)
17
+ field2 = models.CharField(max_length=10)
18
+
19
+ class Meta:
20
+ unique_together = (('field1', 'field2'),)
21
+
22
+
23
+ if django.VERSION < (5, 1):
24
+ # class IndexTogether1(models.Model): # 0001
25
+ class IndexTogether1Renamed(models.Model): # 0002
26
+ """Sequential migrations with index-together fields"""
27
+
28
+ field1 = models.CharField(max_length=10)
29
+ field2 = models.CharField(max_length=10)
30
+
31
+ class Meta:
32
+ index_together = (('field1', 'field2'),)
33
+
34
+
35
+ # class ExplicitConstraint1(models.Model): # 0001
36
+ class ExplicitConstraint1Renamed(models.Model): # 0002
37
+ """Sequential migrations with explicit named constraint in Meta"""
38
+
39
+ field1 = models.CharField(max_length=10)
40
+ field2 = models.CharField(max_length=10)
41
+
42
+ class Meta:
43
+ constraints = [
44
+ models.UniqueConstraint(
45
+ fields=['field1', 'field2'],
46
+ condition=~(models.Q(field1='<empty>') & models.Q(field2='<empty>')),
47
+ name='explicit_model_constraint1_non_empty'
48
+ )
49
+ ]
50
+
51
+
52
+ # class ExplicitIndex1(models.Model): # 0001
53
+ class ExplicitIndex1Renamed(models.Model): # 0002
54
+ """Sequential migrations with explicit named index in Meta"""
55
+
56
+ field1 = models.CharField(max_length=10)
57
+ field2 = models.CharField(max_length=10)
58
+
59
+ class Meta:
60
+ indexes = [models.Index(fields=['field1', 'field2'], name='explicit_model_index1_index')]
@@ -0,0 +1,9 @@
1
+ """Module Tests"""
2
+
3
+ from config import base_tests
4
+
5
+
6
+ class ModuleTest(base_tests.TestCase):
7
+ __doc__ = __doc__
8
+
9
+ module_name = __name__.split('.')[0]