11from contextlib import contextmanager
22from unittest import mock
33
4+ import django
5+
46from django .db .migrations import (
57 AddField ,
68 AlterField ,
1113)
1214from django .db .migrations .autodetector import MigrationAutodetector
1315from django .db .migrations .operations .base import Operation
14- from django .db .models import Model
1516
1617from psqlextra .models import (
1718 PostgresMaterializedViewModel ,
2122from psqlextra .types import PostgresPartitioningMethod
2223
2324from . 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