plain.models 0.49.2__py3-none-any.whl → 0.51.0__py3-none-any.whl
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.
- plain/models/CHANGELOG.md +27 -0
- plain/models/README.md +26 -42
- plain/models/__init__.py +2 -0
- plain/models/aggregates.py +42 -19
- plain/models/backends/base/base.py +125 -105
- plain/models/backends/base/client.py +11 -3
- plain/models/backends/base/creation.py +24 -14
- plain/models/backends/base/features.py +10 -4
- plain/models/backends/base/introspection.py +37 -20
- plain/models/backends/base/operations.py +187 -91
- plain/models/backends/base/schema.py +338 -218
- plain/models/backends/base/validation.py +13 -4
- plain/models/backends/ddl_references.py +85 -43
- plain/models/backends/mysql/base.py +29 -26
- plain/models/backends/mysql/client.py +7 -2
- plain/models/backends/mysql/compiler.py +13 -4
- plain/models/backends/mysql/creation.py +5 -2
- plain/models/backends/mysql/features.py +24 -22
- plain/models/backends/mysql/introspection.py +22 -13
- plain/models/backends/mysql/operations.py +107 -40
- plain/models/backends/mysql/schema.py +52 -28
- plain/models/backends/mysql/validation.py +13 -6
- plain/models/backends/postgresql/base.py +41 -34
- plain/models/backends/postgresql/client.py +7 -2
- plain/models/backends/postgresql/creation.py +10 -5
- plain/models/backends/postgresql/introspection.py +15 -8
- plain/models/backends/postgresql/operations.py +110 -43
- plain/models/backends/postgresql/schema.py +88 -49
- plain/models/backends/sqlite3/_functions.py +151 -115
- plain/models/backends/sqlite3/base.py +37 -23
- plain/models/backends/sqlite3/client.py +7 -1
- plain/models/backends/sqlite3/creation.py +9 -5
- plain/models/backends/sqlite3/features.py +5 -3
- plain/models/backends/sqlite3/introspection.py +32 -16
- plain/models/backends/sqlite3/operations.py +126 -43
- plain/models/backends/sqlite3/schema.py +127 -92
- plain/models/backends/utils.py +52 -29
- plain/models/backups/cli.py +8 -6
- plain/models/backups/clients.py +16 -7
- plain/models/backups/core.py +24 -13
- plain/models/base.py +221 -229
- plain/models/cli.py +98 -67
- plain/models/config.py +1 -1
- plain/models/connections.py +23 -7
- plain/models/constraints.py +79 -56
- plain/models/database_url.py +1 -1
- plain/models/db.py +6 -2
- plain/models/deletion.py +80 -56
- plain/models/entrypoints.py +1 -1
- plain/models/enums.py +22 -11
- plain/models/exceptions.py +23 -8
- plain/models/expressions.py +441 -258
- plain/models/fields/__init__.py +272 -217
- plain/models/fields/json.py +123 -57
- plain/models/fields/mixins.py +12 -8
- plain/models/fields/related.py +324 -290
- plain/models/fields/related_descriptors.py +33 -24
- plain/models/fields/related_lookups.py +24 -12
- plain/models/fields/related_managers.py +102 -79
- plain/models/fields/reverse_related.py +66 -63
- plain/models/forms.py +101 -75
- plain/models/functions/comparison.py +71 -18
- plain/models/functions/datetime.py +79 -29
- plain/models/functions/math.py +43 -10
- plain/models/functions/mixins.py +24 -7
- plain/models/functions/text.py +104 -25
- plain/models/functions/window.py +12 -6
- plain/models/indexes.py +57 -32
- plain/models/lookups.py +228 -153
- plain/models/meta.py +505 -0
- plain/models/migrations/autodetector.py +86 -43
- plain/models/migrations/exceptions.py +7 -3
- plain/models/migrations/executor.py +33 -7
- plain/models/migrations/graph.py +79 -50
- plain/models/migrations/loader.py +45 -22
- plain/models/migrations/migration.py +23 -18
- plain/models/migrations/operations/base.py +38 -20
- plain/models/migrations/operations/fields.py +95 -48
- plain/models/migrations/operations/models.py +246 -142
- plain/models/migrations/operations/special.py +82 -25
- plain/models/migrations/optimizer.py +7 -2
- plain/models/migrations/questioner.py +58 -31
- plain/models/migrations/recorder.py +27 -16
- plain/models/migrations/serializer.py +50 -39
- plain/models/migrations/state.py +232 -156
- plain/models/migrations/utils.py +30 -14
- plain/models/migrations/writer.py +17 -14
- plain/models/options.py +189 -518
- plain/models/otel.py +16 -6
- plain/models/preflight.py +42 -17
- plain/models/query.py +400 -251
- plain/models/query_utils.py +109 -69
- plain/models/registry.py +40 -21
- plain/models/sql/compiler.py +190 -127
- plain/models/sql/datastructures.py +38 -25
- plain/models/sql/query.py +320 -225
- plain/models/sql/subqueries.py +36 -25
- plain/models/sql/where.py +54 -29
- plain/models/test/pytest.py +15 -11
- plain/models/test/utils.py +4 -2
- plain/models/transaction.py +20 -7
- plain/models/utils.py +17 -6
- {plain_models-0.49.2.dist-info → plain_models-0.51.0.dist-info}/METADATA +27 -43
- plain_models-0.51.0.dist-info/RECORD +123 -0
- plain_models-0.49.2.dist-info/RECORD +0 -122
- {plain_models-0.49.2.dist-info → plain_models-0.51.0.dist-info}/WHEEL +0 -0
- {plain_models-0.49.2.dist-info → plain_models-0.51.0.dist-info}/entry_points.txt +0 -0
- {plain_models-0.49.2.dist-info → plain_models-0.51.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,3 +1,13 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from typing import TYPE_CHECKING, Any
|
4
|
+
|
5
|
+
if TYPE_CHECKING:
|
6
|
+
from plain.models.backends.base.base import BaseDatabaseWrapper
|
7
|
+
from plain.models.backends.base.schema import BaseDatabaseSchemaEditor
|
8
|
+
from plain.models.migrations.state import ProjectState
|
9
|
+
|
10
|
+
|
1
11
|
class Operation:
|
2
12
|
"""
|
3
13
|
Base class for migration operations.
|
@@ -24,15 +34,15 @@ class Operation:
|
|
24
34
|
# Should this operation be considered safe to elide and optimize across?
|
25
35
|
elidable = False
|
26
36
|
|
27
|
-
serialization_expand_args = []
|
37
|
+
serialization_expand_args: list[str] = []
|
28
38
|
|
29
|
-
def __new__(cls, *args, **kwargs):
|
39
|
+
def __new__(cls, *args: Any, **kwargs: Any) -> Operation:
|
30
40
|
# We capture the arguments to make returning them trivial
|
31
41
|
self = object.__new__(cls)
|
32
|
-
self._constructor_args = (args, kwargs)
|
33
|
-
return self
|
42
|
+
self._constructor_args = (args, kwargs) # type: ignore[attr-defined]
|
43
|
+
return self # type: ignore[return-value]
|
34
44
|
|
35
|
-
def deconstruct(self):
|
45
|
+
def deconstruct(self) -> tuple[str, tuple[Any, ...], dict[str, Any]]:
|
36
46
|
"""
|
37
47
|
Return a 3-tuple of class import path (or just name if it lives
|
38
48
|
under plain.models.migrations), positional arguments, and keyword
|
@@ -40,11 +50,11 @@ class Operation:
|
|
40
50
|
"""
|
41
51
|
return (
|
42
52
|
self.__class__.__name__,
|
43
|
-
self._constructor_args[0],
|
44
|
-
self._constructor_args[1],
|
53
|
+
self._constructor_args[0], # type: ignore[attr-defined]
|
54
|
+
self._constructor_args[1], # type: ignore[attr-defined]
|
45
55
|
)
|
46
56
|
|
47
|
-
def state_forwards(self, package_label, state):
|
57
|
+
def state_forwards(self, package_label: str, state: ProjectState) -> None:
|
48
58
|
"""
|
49
59
|
Take the state from the previous migration, and mutate it
|
50
60
|
so that it matches what this migration would perform.
|
@@ -53,7 +63,13 @@ class Operation:
|
|
53
63
|
"subclasses of Operation must provide a state_forwards() method"
|
54
64
|
)
|
55
65
|
|
56
|
-
def database_forwards(
|
66
|
+
def database_forwards(
|
67
|
+
self,
|
68
|
+
package_label: str,
|
69
|
+
schema_editor: BaseDatabaseSchemaEditor,
|
70
|
+
from_state: ProjectState,
|
71
|
+
to_state: ProjectState,
|
72
|
+
) -> None:
|
57
73
|
"""
|
58
74
|
Perform the mutation on the database schema in the normal
|
59
75
|
(forwards) direction.
|
@@ -62,21 +78,21 @@ class Operation:
|
|
62
78
|
"subclasses of Operation must provide a database_forwards() method"
|
63
79
|
)
|
64
80
|
|
65
|
-
def describe(self):
|
81
|
+
def describe(self) -> str:
|
66
82
|
"""
|
67
83
|
Output a brief summary of what the action does.
|
68
84
|
"""
|
69
|
-
return f"{self.__class__.__name__}: {self._constructor_args}"
|
85
|
+
return f"{self.__class__.__name__}: {self._constructor_args}" # type: ignore[attr-defined]
|
70
86
|
|
71
87
|
@property
|
72
|
-
def migration_name_fragment(self):
|
88
|
+
def migration_name_fragment(self) -> str | None:
|
73
89
|
"""
|
74
90
|
A filename part suitable for automatically naming a migration
|
75
91
|
containing this operation, or None if not applicable.
|
76
92
|
"""
|
77
93
|
return None
|
78
94
|
|
79
|
-
def references_model(self, name, package_label):
|
95
|
+
def references_model(self, name: str, package_label: str) -> bool:
|
80
96
|
"""
|
81
97
|
Return True if there is a chance this operation references the given
|
82
98
|
model name (as a string), with an app label for accuracy.
|
@@ -88,7 +104,7 @@ class Operation:
|
|
88
104
|
"""
|
89
105
|
return True
|
90
106
|
|
91
|
-
def references_field(self, model_name, name, package_label):
|
107
|
+
def references_field(self, model_name: str, name: str, package_label: str) -> bool:
|
92
108
|
"""
|
93
109
|
Return True if there is a chance this operation references the given
|
94
110
|
field name, with an app label for accuracy.
|
@@ -97,14 +113,16 @@ class Operation:
|
|
97
113
|
"""
|
98
114
|
return self.references_model(model_name, package_label)
|
99
115
|
|
100
|
-
def allow_migrate_model(self, connection, model):
|
116
|
+
def allow_migrate_model(self, connection: BaseDatabaseWrapper, model: Any) -> bool:
|
101
117
|
"""Return whether or not a model may be migrated."""
|
102
|
-
if not model.
|
118
|
+
if not model.model_options.can_migrate(connection):
|
103
119
|
return False
|
104
120
|
|
105
121
|
return True
|
106
122
|
|
107
|
-
def reduce(
|
123
|
+
def reduce(
|
124
|
+
self, operation: Operation, package_label: str
|
125
|
+
) -> list[Operation] | bool:
|
108
126
|
"""
|
109
127
|
Return either a list of operations the actual operation should be
|
110
128
|
replaced with or a boolean that indicates whether or not the specified
|
@@ -116,9 +134,9 @@ class Operation:
|
|
116
134
|
return [self]
|
117
135
|
return False
|
118
136
|
|
119
|
-
def __repr__(self):
|
137
|
+
def __repr__(self) -> str:
|
120
138
|
return "<{} {}{}>".format(
|
121
139
|
self.__class__.__name__,
|
122
|
-
", ".join(map(repr, self._constructor_args[0])),
|
123
|
-
",".join(" {}={!r}".format(*x) for x in self._constructor_args[1].items()),
|
140
|
+
", ".join(map(repr, self._constructor_args[0])), # type: ignore[attr-defined]
|
141
|
+
",".join(" {}={!r}".format(*x) for x in self._constructor_args[1].items()), # type: ignore[attr-defined]
|
124
142
|
)
|
@@ -1,35 +1,43 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
1
3
|
from functools import cached_property
|
4
|
+
from typing import TYPE_CHECKING, Any
|
2
5
|
|
3
6
|
from plain.models.fields import NOT_PROVIDED
|
4
7
|
from plain.models.migrations.utils import field_references
|
5
8
|
|
6
9
|
from .base import Operation
|
7
10
|
|
11
|
+
if TYPE_CHECKING:
|
12
|
+
from plain.models.backends.base.schema import BaseDatabaseSchemaEditor
|
13
|
+
from plain.models.fields import Field
|
14
|
+
from plain.models.migrations.state import ProjectState
|
15
|
+
|
8
16
|
|
9
17
|
class FieldOperation(Operation):
|
10
|
-
def __init__(self, model_name, name, field=None):
|
18
|
+
def __init__(self, model_name: str, name: str, field: Field | None = None) -> None:
|
11
19
|
self.model_name = model_name
|
12
20
|
self.name = name
|
13
21
|
self.field = field
|
14
22
|
|
15
23
|
@cached_property
|
16
|
-
def model_name_lower(self):
|
24
|
+
def model_name_lower(self) -> str:
|
17
25
|
return self.model_name.lower()
|
18
26
|
|
19
27
|
@cached_property
|
20
|
-
def name_lower(self):
|
28
|
+
def name_lower(self) -> str:
|
21
29
|
return self.name.lower()
|
22
30
|
|
23
|
-
def is_same_model_operation(self, operation):
|
31
|
+
def is_same_model_operation(self, operation: FieldOperation) -> bool:
|
24
32
|
return self.model_name_lower == operation.model_name_lower
|
25
33
|
|
26
|
-
def is_same_field_operation(self, operation):
|
34
|
+
def is_same_field_operation(self, operation: FieldOperation) -> bool:
|
27
35
|
return (
|
28
36
|
self.is_same_model_operation(operation)
|
29
37
|
and self.name_lower == operation.name_lower
|
30
38
|
)
|
31
39
|
|
32
|
-
def references_model(self, name, package_label):
|
40
|
+
def references_model(self, name: str, package_label: str) -> bool:
|
33
41
|
name_lower = name.lower()
|
34
42
|
if name_lower == self.model_name_lower:
|
35
43
|
return True
|
@@ -43,7 +51,7 @@ class FieldOperation(Operation):
|
|
43
51
|
)
|
44
52
|
return False
|
45
53
|
|
46
|
-
def references_field(self, model_name, name, package_label):
|
54
|
+
def references_field(self, model_name: str, name: str, package_label: str) -> bool:
|
47
55
|
model_name_lower = model_name.lower()
|
48
56
|
# Check if this operation locally references the field.
|
49
57
|
if model_name_lower == self.model_name_lower:
|
@@ -61,7 +69,9 @@ class FieldOperation(Operation):
|
|
61
69
|
)
|
62
70
|
)
|
63
71
|
|
64
|
-
def reduce(
|
72
|
+
def reduce(
|
73
|
+
self, operation: Operation, package_label: str
|
74
|
+
) -> list[Operation] | bool:
|
65
75
|
return super().reduce(
|
66
76
|
operation, package_label
|
67
77
|
) or not operation.references_field(self.model_name, self.name, package_label)
|
@@ -70,12 +80,14 @@ class FieldOperation(Operation):
|
|
70
80
|
class AddField(FieldOperation):
|
71
81
|
"""Add a field to a model."""
|
72
82
|
|
73
|
-
def __init__(
|
83
|
+
def __init__(
|
84
|
+
self, model_name: str, name: str, field: Field, preserve_default: bool = True
|
85
|
+
) -> None:
|
74
86
|
self.preserve_default = preserve_default
|
75
87
|
super().__init__(model_name, name, field)
|
76
88
|
|
77
|
-
def deconstruct(self):
|
78
|
-
kwargs = {
|
89
|
+
def deconstruct(self) -> tuple[str, list[Any], dict[str, Any]]:
|
90
|
+
kwargs: dict[str, Any] = {
|
79
91
|
"model_name": self.model_name,
|
80
92
|
"name": self.name,
|
81
93
|
"field": self.field,
|
@@ -84,7 +96,7 @@ class AddField(FieldOperation):
|
|
84
96
|
kwargs["preserve_default"] = self.preserve_default
|
85
97
|
return (self.__class__.__name__, [], kwargs)
|
86
98
|
|
87
|
-
def state_forwards(self, package_label, state):
|
99
|
+
def state_forwards(self, package_label: str, state: Any) -> None:
|
88
100
|
state.add_field(
|
89
101
|
package_label,
|
90
102
|
self.model_name_lower,
|
@@ -93,13 +105,19 @@ class AddField(FieldOperation):
|
|
93
105
|
self.preserve_default,
|
94
106
|
)
|
95
107
|
|
96
|
-
def database_forwards(
|
108
|
+
def database_forwards(
|
109
|
+
self,
|
110
|
+
package_label: str,
|
111
|
+
schema_editor: BaseDatabaseSchemaEditor,
|
112
|
+
from_state: ProjectState,
|
113
|
+
to_state: ProjectState,
|
114
|
+
) -> None:
|
97
115
|
to_model = to_state.models_registry.get_model(package_label, self.model_name)
|
98
116
|
if self.allow_migrate_model(schema_editor.connection, to_model):
|
99
117
|
from_model = from_state.models_registry.get_model(
|
100
118
|
package_label, self.model_name
|
101
119
|
)
|
102
|
-
field = to_model.
|
120
|
+
field = to_model._model_meta.get_field(self.name)
|
103
121
|
if not self.preserve_default:
|
104
122
|
field.default = self.field.default
|
105
123
|
schema_editor.add_field(
|
@@ -109,18 +127,21 @@ class AddField(FieldOperation):
|
|
109
127
|
if not self.preserve_default:
|
110
128
|
field.default = NOT_PROVIDED
|
111
129
|
|
112
|
-
def describe(self):
|
130
|
+
def describe(self) -> str:
|
113
131
|
return f"Add field {self.name} to {self.model_name}"
|
114
132
|
|
115
133
|
@property
|
116
|
-
def migration_name_fragment(self):
|
134
|
+
def migration_name_fragment(self) -> str:
|
117
135
|
return f"{self.model_name_lower}_{self.name_lower}"
|
118
136
|
|
119
|
-
def reduce(
|
137
|
+
def reduce(
|
138
|
+
self, operation: Operation, package_label: str
|
139
|
+
) -> list[Operation] | bool:
|
120
140
|
if isinstance(operation, FieldOperation) and self.is_same_field_operation(
|
121
141
|
operation
|
122
142
|
):
|
123
143
|
if isinstance(operation, AlterField):
|
144
|
+
assert operation.field is not None
|
124
145
|
return [
|
125
146
|
AddField(
|
126
147
|
model_name=self.model_name,
|
@@ -144,33 +165,41 @@ class AddField(FieldOperation):
|
|
144
165
|
class RemoveField(FieldOperation):
|
145
166
|
"""Remove a field from a model."""
|
146
167
|
|
147
|
-
def deconstruct(self):
|
148
|
-
kwargs = {
|
168
|
+
def deconstruct(self) -> tuple[str, list[Any], dict[str, Any]]:
|
169
|
+
kwargs: dict[str, Any] = {
|
149
170
|
"model_name": self.model_name,
|
150
171
|
"name": self.name,
|
151
172
|
}
|
152
173
|
return (self.__class__.__name__, [], kwargs)
|
153
174
|
|
154
|
-
def state_forwards(self, package_label, state):
|
175
|
+
def state_forwards(self, package_label: str, state: Any) -> None:
|
155
176
|
state.remove_field(package_label, self.model_name_lower, self.name)
|
156
177
|
|
157
|
-
def database_forwards(
|
178
|
+
def database_forwards(
|
179
|
+
self,
|
180
|
+
package_label: str,
|
181
|
+
schema_editor: BaseDatabaseSchemaEditor,
|
182
|
+
from_state: ProjectState,
|
183
|
+
to_state: ProjectState,
|
184
|
+
) -> None:
|
158
185
|
from_model = from_state.models_registry.get_model(
|
159
186
|
package_label, self.model_name
|
160
187
|
)
|
161
188
|
if self.allow_migrate_model(schema_editor.connection, from_model):
|
162
189
|
schema_editor.remove_field(
|
163
|
-
from_model, from_model.
|
190
|
+
from_model, from_model._model_meta.get_field(self.name)
|
164
191
|
)
|
165
192
|
|
166
|
-
def describe(self):
|
193
|
+
def describe(self) -> str:
|
167
194
|
return f"Remove field {self.name} from {self.model_name}"
|
168
195
|
|
169
196
|
@property
|
170
|
-
def migration_name_fragment(self):
|
197
|
+
def migration_name_fragment(self) -> str:
|
171
198
|
return f"remove_{self.model_name_lower}_{self.name_lower}"
|
172
199
|
|
173
|
-
def reduce(
|
200
|
+
def reduce(
|
201
|
+
self, operation: Operation, package_label: str
|
202
|
+
) -> list[Operation] | bool:
|
174
203
|
from .models import DeleteModel
|
175
204
|
|
176
205
|
if (
|
@@ -187,12 +216,14 @@ class AlterField(FieldOperation):
|
|
187
216
|
new field.
|
188
217
|
"""
|
189
218
|
|
190
|
-
def __init__(
|
219
|
+
def __init__(
|
220
|
+
self, model_name: str, name: str, field: Field, preserve_default: bool = True
|
221
|
+
) -> None:
|
191
222
|
self.preserve_default = preserve_default
|
192
223
|
super().__init__(model_name, name, field)
|
193
224
|
|
194
|
-
def deconstruct(self):
|
195
|
-
kwargs = {
|
225
|
+
def deconstruct(self) -> tuple[str, list[Any], dict[str, Any]]:
|
226
|
+
kwargs: dict[str, Any] = {
|
196
227
|
"model_name": self.model_name,
|
197
228
|
"name": self.name,
|
198
229
|
"field": self.field,
|
@@ -201,7 +232,7 @@ class AlterField(FieldOperation):
|
|
201
232
|
kwargs["preserve_default"] = self.preserve_default
|
202
233
|
return (self.__class__.__name__, [], kwargs)
|
203
234
|
|
204
|
-
def state_forwards(self, package_label, state):
|
235
|
+
def state_forwards(self, package_label: str, state: Any) -> None:
|
205
236
|
state.alter_field(
|
206
237
|
package_label,
|
207
238
|
self.model_name_lower,
|
@@ -210,28 +241,36 @@ class AlterField(FieldOperation):
|
|
210
241
|
self.preserve_default,
|
211
242
|
)
|
212
243
|
|
213
|
-
def database_forwards(
|
244
|
+
def database_forwards(
|
245
|
+
self,
|
246
|
+
package_label: str,
|
247
|
+
schema_editor: BaseDatabaseSchemaEditor,
|
248
|
+
from_state: ProjectState,
|
249
|
+
to_state: ProjectState,
|
250
|
+
) -> None:
|
214
251
|
to_model = to_state.models_registry.get_model(package_label, self.model_name)
|
215
252
|
if self.allow_migrate_model(schema_editor.connection, to_model):
|
216
253
|
from_model = from_state.models_registry.get_model(
|
217
254
|
package_label, self.model_name
|
218
255
|
)
|
219
|
-
from_field = from_model.
|
220
|
-
to_field = to_model.
|
256
|
+
from_field = from_model._model_meta.get_field(self.name)
|
257
|
+
to_field = to_model._model_meta.get_field(self.name)
|
221
258
|
if not self.preserve_default:
|
222
259
|
to_field.default = self.field.default
|
223
260
|
schema_editor.alter_field(from_model, from_field, to_field)
|
224
261
|
if not self.preserve_default:
|
225
262
|
to_field.default = NOT_PROVIDED
|
226
263
|
|
227
|
-
def describe(self):
|
264
|
+
def describe(self) -> str:
|
228
265
|
return f"Alter field {self.name} on {self.model_name}"
|
229
266
|
|
230
267
|
@property
|
231
|
-
def migration_name_fragment(self):
|
268
|
+
def migration_name_fragment(self) -> str:
|
232
269
|
return f"alter_{self.model_name_lower}_{self.name_lower}"
|
233
270
|
|
234
|
-
def reduce(
|
271
|
+
def reduce(
|
272
|
+
self, operation: Operation, package_label: str
|
273
|
+
) -> list[Operation] | bool:
|
235
274
|
if isinstance(
|
236
275
|
operation, AlterField | RemoveField
|
237
276
|
) and self.is_same_field_operation(operation):
|
@@ -255,33 +294,39 @@ class AlterField(FieldOperation):
|
|
255
294
|
class RenameField(FieldOperation):
|
256
295
|
"""Rename a field on the model. Might affect db_column too."""
|
257
296
|
|
258
|
-
def __init__(self, model_name, old_name, new_name):
|
297
|
+
def __init__(self, model_name: str, old_name: str, new_name: str) -> None:
|
259
298
|
self.old_name = old_name
|
260
299
|
self.new_name = new_name
|
261
300
|
super().__init__(model_name, old_name)
|
262
301
|
|
263
302
|
@cached_property
|
264
|
-
def old_name_lower(self):
|
303
|
+
def old_name_lower(self) -> str:
|
265
304
|
return self.old_name.lower()
|
266
305
|
|
267
306
|
@cached_property
|
268
|
-
def new_name_lower(self):
|
307
|
+
def new_name_lower(self) -> str:
|
269
308
|
return self.new_name.lower()
|
270
309
|
|
271
|
-
def deconstruct(self):
|
272
|
-
kwargs = {
|
310
|
+
def deconstruct(self) -> tuple[str, list[Any], dict[str, Any]]:
|
311
|
+
kwargs: dict[str, Any] = {
|
273
312
|
"model_name": self.model_name,
|
274
313
|
"old_name": self.old_name,
|
275
314
|
"new_name": self.new_name,
|
276
315
|
}
|
277
316
|
return (self.__class__.__name__, [], kwargs)
|
278
317
|
|
279
|
-
def state_forwards(self, package_label, state):
|
318
|
+
def state_forwards(self, package_label: str, state: Any) -> None:
|
280
319
|
state.rename_field(
|
281
320
|
package_label, self.model_name_lower, self.old_name, self.new_name
|
282
321
|
)
|
283
322
|
|
284
|
-
def database_forwards(
|
323
|
+
def database_forwards(
|
324
|
+
self,
|
325
|
+
package_label: str,
|
326
|
+
schema_editor: BaseDatabaseSchemaEditor,
|
327
|
+
from_state: ProjectState,
|
328
|
+
to_state: ProjectState,
|
329
|
+
) -> None:
|
285
330
|
to_model = to_state.models_registry.get_model(package_label, self.model_name)
|
286
331
|
if self.allow_migrate_model(schema_editor.connection, to_model):
|
287
332
|
from_model = from_state.models_registry.get_model(
|
@@ -289,23 +334,25 @@ class RenameField(FieldOperation):
|
|
289
334
|
)
|
290
335
|
schema_editor.alter_field(
|
291
336
|
from_model,
|
292
|
-
from_model.
|
293
|
-
to_model.
|
337
|
+
from_model._model_meta.get_field(self.old_name),
|
338
|
+
to_model._model_meta.get_field(self.new_name),
|
294
339
|
)
|
295
340
|
|
296
|
-
def describe(self):
|
341
|
+
def describe(self) -> str:
|
297
342
|
return f"Rename field {self.old_name} on {self.model_name} to {self.new_name}"
|
298
343
|
|
299
344
|
@property
|
300
|
-
def migration_name_fragment(self):
|
345
|
+
def migration_name_fragment(self) -> str:
|
301
346
|
return f"rename_{self.old_name_lower}_{self.model_name_lower}_{self.new_name_lower}"
|
302
347
|
|
303
|
-
def references_field(self, model_name, name, package_label):
|
348
|
+
def references_field(self, model_name: str, name: str, package_label: str) -> bool:
|
304
349
|
return self.references_model(model_name, package_label) and (
|
305
350
|
name.lower() == self.old_name_lower or name.lower() == self.new_name_lower
|
306
351
|
)
|
307
352
|
|
308
|
-
def reduce(
|
353
|
+
def reduce(
|
354
|
+
self, operation: Operation, package_label: str
|
355
|
+
) -> list[Operation] | bool:
|
309
356
|
if (
|
310
357
|
isinstance(operation, RenameField)
|
311
358
|
and self.is_same_model_operation(operation)
|