summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
authorAndrew Godwin <andrew@aeracode.org>2013-06-20 15:12:59 +0100
committerAndrew Godwin <andrew@aeracode.org>2013-06-20 15:12:59 +0100
commit80bdf68d6b5fd44056479ccc74cd24281b787a64 (patch)
tree8ce30bba063a2a8a8cb9395e2a403fc0d228fbe6 /django
parent6f667999e1186b8eaa9c86e4cbd80d5c0ba20576 (diff)
Add AlterField and RenameField operations
Diffstat (limited to 'django')
-rw-r--r--django/db/migrations/operations/__init__.py2
-rw-r--r--django/db/migrations/operations/fields.py68
-rw-r--r--django/db/migrations/state.py9
3 files changed, 77 insertions, 2 deletions
diff --git a/django/db/migrations/operations/__init__.py b/django/db/migrations/operations/__init__.py
index 6c2c784635..925b05fff3 100644
--- a/django/db/migrations/operations/__init__.py
+++ b/django/db/migrations/operations/__init__.py
@@ -1,2 +1,2 @@
from .models import CreateModel, DeleteModel, AlterModelTable
-from .fields import AddField, RemoveField
+from .fields import AddField, RemoveField, AlterField, RenameField
diff --git a/django/db/migrations/operations/fields.py b/django/db/migrations/operations/fields.py
index 660cba6b72..cc4f4a43df 100644
--- a/django/db/migrations/operations/fields.py
+++ b/django/db/migrations/operations/fields.py
@@ -54,3 +54,71 @@ class RemoveField(Operation):
def describe(self):
return "Remove field %s from %s" % (self.name, self.model_name)
+
+
+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
+ self.name = name
+ self.field = field
+
+ def state_forwards(self, app_label, state):
+ state.models[app_label, self.model_name.lower()].fields = [
+ (n, self.field if n == self.name else f) for n, f in state.models[app_label, self.model_name.lower()].fields
+ ]
+
+ def database_forwards(self, app_label, schema_editor, from_state, to_state):
+ from_model = from_state.render().get_model(app_label, self.model_name)
+ to_model = to_state.render().get_model(app_label, self.model_name)
+ schema_editor.alter_field(
+ from_model,
+ from_model._meta.get_field_by_name(self.name)[0],
+ to_model._meta.get_field_by_name(self.name)[0],
+ )
+
+ def database_backwards(self, app_label, schema_editor, from_state, to_state):
+ self.database_forwards(app_label, schema_editor, from_state, to_state)
+
+ def describe(self):
+ return "Alter field %s on %s" % (self.name, self.model_name)
+
+
+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
+ self.old_name = old_name
+ self.new_name = new_name
+
+ def state_forwards(self, app_label, state):
+ state.models[app_label, self.model_name.lower()].fields = [
+ (self.new_name if n == self.old_name else n, f) for n, f in state.models[app_label, self.model_name.lower()].fields
+ ]
+
+ def database_forwards(self, app_label, schema_editor, from_state, to_state):
+ from_model = from_state.render().get_model(app_label, self.model_name)
+ to_model = to_state.render().get_model(app_label, self.model_name)
+ schema_editor.alter_field(
+ from_model,
+ from_model._meta.get_field_by_name(self.old_name)[0],
+ to_model._meta.get_field_by_name(self.new_name)[0],
+ )
+
+ def database_backwards(self, app_label, schema_editor, from_state, to_state):
+ from_model = from_state.render().get_model(app_label, self.model_name)
+ to_model = to_state.render().get_model(app_label, self.model_name)
+ schema_editor.alter_field(
+ from_model,
+ from_model._meta.get_field_by_name(self.new_name)[0],
+ to_model._meta.get_field_by_name(self.old_name)[0],
+ )
+
+ def describe(self):
+ return "Rename field %s on %s to %s" % (self.old_name, self.model_name, self.new_name)
diff --git a/django/db/migrations/state.py b/django/db/migrations/state.py
index b6618041f2..65b749c80c 100644
--- a/django/db/migrations/state.py
+++ b/django/db/migrations/state.py
@@ -93,10 +93,17 @@ class ModelState(object):
def clone(self):
"Returns an exact copy of this ModelState"
+ # We deep-clone the fields using deconstruction
+ fields = []
+ for name, field in self.fields:
+ _, path, args, kwargs = field.deconstruct()
+ field_class = import_by_path(path)
+ fields.append((name, field_class(*args, **kwargs)))
+ # Now make a copy
return self.__class__(
app_label = self.app_label,
name = self.name,
- fields = list(self.fields),
+ fields = fields,
options = dict(self.options),
bases = self.bases,
)