Permalink
Browse files

Massive migration optimiser improvements + RenameModel opn

  • Loading branch information...
1 parent 8265323 commit 106b019dc9b48aa749947e406e5445feb045e8a2 @andrewgodwin andrewgodwin committed Nov 6, 2013
@@ -1,11 +1,11 @@
from .models import (CreateModel, DeleteModel, AlterModelTable,
- AlterUniqueTogether, AlterIndexTogether)
+ AlterUniqueTogether, AlterIndexTogether, RenameModel)
from .fields import AddField, RemoveField, AlterField, RenameField
from .special import SeparateDatabaseAndState, RunSQL, RunPython
__all__ = [
'CreateModel', 'DeleteModel', 'AlterModelTable', 'AlterUniqueTogether',
- 'AlterIndexTogether',
+ 'RenameModel', 'AlterIndexTogether',
'AddField', 'RemoveField', 'AlterField', 'RenameField',
'SeparateDatabaseAndState', 'RunSQL', 'RunPython',
]
@@ -9,6 +9,9 @@ class Operation(object):
Note that some operations won't modify memory state at all (e.g. data
copying operations), and some will need their modifications to be
optionally specified by the user (e.g. custom Python code snippets)
+
+ Due to the way this class deals with deconstruction, it should be
+ considered immutable.
"""
# If this migration can be run in reverse.
@@ -76,6 +79,15 @@ def references_model(self, name, app_label=None):
"""
return True
+ def references_field(self, model_name, name, app_label=None):
+ """
+ Returns True if there is a chance this operation references the given
+ field name, with an optional app label for accuracy.
+
+ Used for optimization. If in doubt, return True.
+ """
+ return self.references_model(model_name, app_label)
+
def __repr__(self):
return "<%s %s%s>" % (
self.__class__.__name__,
@@ -8,7 +8,7 @@ class AddField(Operation):
"""
def __init__(self, model_name, name, field):
- self.model_name = model_name.lower()
+ self.model_name = model_name
self.name = name
self.field = field
@@ -33,18 +33,24 @@ def __eq__(self, other):
return (
(self.__class__ == other.__class__) and
(self.name == other.name) and
- (self.model_name == other.model_name) and
+ (self.model_name.lower() == other.model_name.lower()) and
(self.field.deconstruct()[1:] == other.field.deconstruct()[1:])
)
+ def references_model(self, name, app_label=None):
+ return name.lower() == self.model_name.lower()
+
+ def references_field(self, model_name, name, app_label=None):
+ return self.references_model(model_name) and name.lower() == self.name.lower()
+
class RemoveField(Operation):
"""
Removes a field from a model.
"""
def __init__(self, model_name, name):
- self.model_name = model_name.lower()
+ self.model_name = model_name
self.name = name
def state_forwards(self, app_label, state):
@@ -68,14 +74,20 @@ def database_backwards(self, app_label, schema_editor, from_state, to_state):
def describe(self):
return "Remove field %s from %s" % (self.name, self.model_name)
+ def references_model(self, name, app_label=None):
+ return name.lower() == self.model_name.lower()
+
+ def references_field(self, model_name, name, app_label=None):
+ return self.references_model(model_name) and name.lower() == self.name.lower()
+
class AlterField(Operation):
"""
Alters a field's database column (e.g. null, max_length) to the provided new field
"""
def __init__(self, model_name, name, field):
- self.model_name = model_name.lower()
+ self.model_name = model_name
self.name = name
self.field = field
@@ -104,18 +116,24 @@ def __eq__(self, other):
return (
(self.__class__ == other.__class__) and
(self.name == other.name) and
- (self.model_name == other.model_name) and
+ (self.model_name.lower() == other.model_name.lower()) and
(self.field.deconstruct()[1:] == other.field.deconstruct()[1:])
)
+ def references_model(self, name, app_label=None):
+ return name.lower() == self.model_name.lower()
+
+ def references_field(self, model_name, name, app_label=None):
+ return self.references_model(model_name) and name.lower() == self.name.lower()
+
class RenameField(Operation):
"""
Renames a field on the model. Might affect db_column too.
"""
def __init__(self, model_name, old_name, new_name):
- self.model_name = model_name.lower()
+ self.model_name = model_name
self.old_name = old_name
self.new_name = new_name
@@ -146,3 +164,12 @@ def database_backwards(self, app_label, schema_editor, from_state, to_state):
def describe(self):
return "Rename field %s on %s to %s" % (self.old_name, self.model_name, self.new_name)
+
+ def references_model(self, name, app_label=None):
+ return name.lower() == self.model_name.lower()
+
+ def references_field(self, model_name, name, app_label=None):
+ return self.references_model(model_name) and (
+ name.lower() == self.old_name.lower() or
+ name.lower() == self.new_name.lower()
+ )
@@ -91,6 +91,54 @@ def describe(self):
return "Delete model %s" % (self.name, )
+class RenameModel(Operation):
+ """
+ Renames a model.
+ """
+
+ def __init__(self, old_name, new_name):
+ self.old_name = old_name
+ self.new_name = new_name
+
+ def state_forwards(self, app_label, state):
+ state.models[app_label, self.new_name.lower()] = state.models[app_label, self.old_name.lower()]
+ state.models[app_label, self.new_name.lower()].name = self.new_name
+ del state.models[app_label, self.old_name.lower()]
+
+ def database_forwards(self, app_label, schema_editor, from_state, to_state):
+ old_app_cache = from_state.render()
+ new_app_cache = to_state.render()
+ old_model = old_app_cache.get_model(app_label, self.old_name)
+ new_model = new_app_cache.get_model(app_label, self.new_name)
+ if router.allow_migrate(schema_editor.connection.alias, new_model):
+ schema_editor.alter_db_table(
+ new_model,
+ old_model._meta.db_table,
+ new_model._meta.db_table,
+ )
+
+ def database_backwards(self, app_label, schema_editor, from_state, to_state):
+ old_app_cache = from_state.render()
+ new_app_cache = to_state.render()
+ old_model = old_app_cache.get_model(app_label, self.new_name)
+ new_model = new_app_cache.get_model(app_label, self.old_name)
+ if router.allow_migrate(schema_editor.connection.alias, new_model):
+ schema_editor.alter_db_table(
+ new_model,
+ old_model._meta.db_table,
+ new_model._meta.db_table,
+ )
+
+ def references_model(self, name, app_label=None):
+ return (
+ name.lower() == self.old_name.lower() or
+ name.lower() == self.new_name.lower()
+ )
+
+ def describe(self):
+ return "Rename model %s to %s" % (self.old_name, self.new_name)
+
+
class AlterModelTable(Operation):
"""
Renames a model's table
Oops, something went wrong.

0 comments on commit 106b019

Please sign in to comment.