Skip to content

Commit 269e379

Browse files
committed
Make migration auto detector work with Django 4.x
django/django@aa4acc1#diff-50cc08301fdd233fd64196aa90bc684d96ef557d99af67692995559646de567a Django changd from using models to model state in the auto detector.
1 parent 03d71ae commit 269e379

File tree

1 file changed

+108
-42
lines changed

1 file changed

+108
-42
lines changed

psqlextra/backend/migrations/patched_autodetector.py

Lines changed: 108 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
from contextlib import contextmanager
22
from unittest import mock
33

4+
import django
5+
46
from django.db.migrations import (
57
AddField,
68
AlterField,
@@ -11,7 +13,6 @@
1113
)
1214
from django.db.migrations.autodetector import MigrationAutodetector
1315
from django.db.migrations.operations.base import Operation
14-
from django.db.models import Model
1516

1617
from psqlextra.models import (
1718
PostgresMaterializedViewModel,
@@ -21,6 +22,11 @@
2122
from psqlextra.types import PostgresPartitioningMethod
2223

2324
from . import operations
25+
from .state import (
26+
PostgresMaterializedViewModelState,
27+
PostgresPartitionedModelState,
28+
PostgresViewModelState,
29+
)
2430

2531
# original `MigrationAutodetector.add_operation`
2632
# function, saved here so the patched version can
@@ -88,62 +94,108 @@ def _transform_view_field_operations(self, operation: Operation):
8894
actually applying it.
8995
"""
9096

91-
model = self.autodetector.new_apps.get_model(
92-
self.app_label, operation.model_name
93-
)
97+
if django.VERSION >= (4, 0):
98+
model_identifier = (self.app_label, operation.model_name.lower())
99+
model_state = (
100+
self.autodetector.to_state.models.get(model_identifier)
101+
or self.autodetector.from_state.models[model_identifier]
102+
)
94103

95-
if issubclass(model, PostgresViewModel):
96-
return self.add(operations.ApplyState(state_operation=operation))
104+
if isinstance(model_state, PostgresViewModelState):
105+
return self.add(
106+
operations.ApplyState(state_operation=operation)
107+
)
108+
else:
109+
model = self.autodetector.new_apps.get_model(
110+
self.app_label, operation.model_name
111+
)
112+
113+
if issubclass(model, PostgresViewModel):
114+
return self.add(
115+
operations.ApplyState(state_operation=operation)
116+
)
97117

98118
return self.add(operation)
99119

100120
def add_create_model(self, operation: CreateModel):
101121
"""Adds the specified :see:CreateModel operation to the list of
102122
operations to execute in the migration."""
103123

104-
model = self.autodetector.new_apps.get_model(
105-
self.app_label, operation.name
106-
)
124+
if django.VERSION >= (4, 0):
125+
model_state = self.autodetector.to_state.models[
126+
self.app_label, operation.name.lower()
127+
]
128+
129+
if isinstance(model_state, PostgresPartitionedModelState):
130+
return self.add_create_partitioned_model(operation)
131+
elif isinstance(model_state, PostgresMaterializedViewModelState):
132+
return self.add_create_materialized_view_model(operation)
133+
elif isinstance(model_state, PostgresViewModelState):
134+
return self.add_create_view_model(operation)
135+
else:
136+
model = self.autodetector.new_apps.get_model(
137+
self.app_label, operation.name
138+
)
107139

108-
if issubclass(model, PostgresPartitionedModel):
109-
return self.add_create_partitioned_model(model, operation)
110-
elif issubclass(model, PostgresMaterializedViewModel):
111-
return self.add_create_materialized_view_model(model, operation)
112-
elif issubclass(model, PostgresViewModel):
113-
return self.add_create_view_model(model, operation)
140+
if issubclass(model, PostgresPartitionedModel):
141+
return self.add_create_partitioned_model(operation)
142+
elif issubclass(model, PostgresMaterializedViewModel):
143+
return self.add_create_materialized_view_model(operation)
144+
elif issubclass(model, PostgresViewModel):
145+
return self.add_create_view_model(operation)
114146

115147
return self.add(operation)
116148

117149
def add_delete_model(self, operation: DeleteModel):
118150
"""Adds the specified :see:Deletemodel operation to the list of
119151
operations to execute in the migration."""
120152

121-
model = self.autodetector.old_apps.get_model(
122-
self.app_label, operation.name
123-
)
153+
if django.VERSION >= (4, 0):
154+
model_state = self.autodetector.from_state.models[
155+
self.app_label, operation.name.lower()
156+
]
157+
158+
if isinstance(model_state, PostgresPartitionedModelState):
159+
return self.add_delete_partitioned_model(operation)
160+
elif isinstance(model_state, PostgresMaterializedViewModelState):
161+
return self.add_delete_materialized_view_model(operation)
162+
elif isinstance(model_state, PostgresViewModelState):
163+
return self.add_delete_view_model(operation)
164+
else:
165+
model = self.autodetector.old_apps.get_model(
166+
self.app_label, operation.name
167+
)
124168

125-
if issubclass(model, PostgresPartitionedModel):
126-
return self.add_delete_partitioned_model(model, operation)
127-
elif issubclass(model, PostgresMaterializedViewModel):
128-
return self.add_delete_materialized_view_model(model, operation)
129-
elif issubclass(model, PostgresViewModel):
130-
return self.add_delete_view_model(model, operation)
169+
if issubclass(model, PostgresPartitionedModel):
170+
return self.add_delete_partitioned_model(operation)
171+
elif issubclass(model, PostgresMaterializedViewModel):
172+
return self.add_delete_materialized_view_model(operation)
173+
elif issubclass(model, PostgresViewModel):
174+
return self.add_delete_view_model(operation)
131175

132176
return self.add(operation)
133177

134-
def add_create_partitioned_model(
135-
self, model: Model, operation: CreateModel
136-
):
178+
def add_create_partitioned_model(self, operation: CreateModel):
137179
"""Adds a :see:PostgresCreatePartitionedModel operation to the list of
138180
operations to execute in the migration."""
139181

140-
partitioning_options = model._partitioning_meta.original_attrs
182+
if django.VERSION >= (4, 0):
183+
model_state = self.autodetector.to_state.models[
184+
self.app_label, operation.name.lower()
185+
]
186+
partitioning_options = model_state.partitioning_options
187+
else:
188+
model = self.autodetector.new_apps.get_model(
189+
self.app_label, operation.name
190+
)
191+
partitioning_options = model._partitioning_meta.original_attrs
192+
141193
_, args, kwargs = operation.deconstruct()
142194

143195
if partitioning_options["method"] != PostgresPartitioningMethod.HASH:
144196
self.add(
145197
operations.PostgresAddDefaultPartition(
146-
model_name=model.__name__, name="default"
198+
model_name=operation.name, name="default"
147199
)
148200
)
149201

@@ -153,9 +205,7 @@ def add_create_partitioned_model(
153205
)
154206
)
155207

156-
def add_delete_partitioned_model(
157-
self, model: Model, operation: DeleteModel
158-
):
208+
def add_delete_partitioned_model(self, operation: DeleteModel):
159209
"""Adds a :see:PostgresDeletePartitionedModel operation to the list of
160210
operations to execute in the migration."""
161211

@@ -164,11 +214,21 @@ def add_delete_partitioned_model(
164214
operations.PostgresDeletePartitionedModel(*args, **kwargs)
165215
)
166216

167-
def add_create_view_model(self, model: Model, operation: CreateModel):
217+
def add_create_view_model(self, operation: CreateModel):
168218
"""Adds a :see:PostgresCreateViewModel operation to the list of
169219
operations to execute in the migration."""
170220

171-
view_options = model._view_meta.original_attrs
221+
if django.VERSION >= (4, 0):
222+
model_state = self.autodetector.to_state.models[
223+
self.app_label, operation.name.lower()
224+
]
225+
view_options = model_state.view_options
226+
else:
227+
model = self.autodetector.new_apps.get_model(
228+
self.app_label, operation.name
229+
)
230+
view_options = model._view_meta.original_attrs
231+
172232
_, args, kwargs = operation.deconstruct()
173233

174234
self.add(
@@ -177,20 +237,28 @@ def add_create_view_model(self, model: Model, operation: CreateModel):
177237
)
178238
)
179239

180-
def add_delete_view_model(self, model: Model, operation: DeleteModel):
240+
def add_delete_view_model(self, operation: DeleteModel):
181241
"""Adds a :see:PostgresDeleteViewModel operation to the list of
182242
operations to execute in the migration."""
183243

184244
_, args, kwargs = operation.deconstruct()
185245
return self.add(operations.PostgresDeleteViewModel(*args, **kwargs))
186246

187-
def add_create_materialized_view_model(
188-
self, model: Model, operation: CreateModel
189-
):
247+
def add_create_materialized_view_model(self, operation: CreateModel):
190248
"""Adds a :see:PostgresCreateMaterializedViewModel operation to the
191249
list of operations to execute in the migration."""
192250

193-
view_options = model._view_meta.original_attrs
251+
if django.VERSION >= (4, 0):
252+
model_state = self.autodetector.to_state.models[
253+
self.app_label, operation.name.lower()
254+
]
255+
view_options = model_state.view_options
256+
else:
257+
model = self.autodetector.new_apps.get_model(
258+
self.app_label, operation.name
259+
)
260+
view_options = model._view_meta.original_attrs
261+
194262
_, args, kwargs = operation.deconstruct()
195263

196264
self.add(
@@ -199,9 +267,7 @@ def add_create_materialized_view_model(
199267
)
200268
)
201269

202-
def add_delete_materialized_view_model(
203-
self, model: Model, operation: DeleteModel
204-
):
270+
def add_delete_materialized_view_model(self, operation: DeleteModel):
205271
"""Adds a :see:PostgresDeleteMaterializedViewModel operation to the
206272
list of operations to execute in the migration."""
207273

0 commit comments

Comments
 (0)