Current situation, caused by legacy:
class Foo(models.Model)
field = models.BooleanField()
@property
def renamed_field(self):
return self.field
@renamed_field.setter
def renamed_field(self, value):
self.field = value
obsolete_field = models.BooleanField()
Desired situation:
class Foo(models.Model)
renamed_field = models.BooleanField()
No problem yet. South can handle the migration using db.rename_column
and db.deletecolumn
.
Problem: our Django app runs on multiple instances with a shared MySQL instance. When we deploy our code to production, we replace old instances with new instances one by one as new instances are booted. If we want to avoid downtime, the app models needs to support the new database scheme, and here's the catch: and while instances are replaced also the old database scheme.
We would like to avoid downtime.
A naive solution would be a two-step approach where we deploy, wait until all instances have been replaced, migrate, and enable the my_feature_switch
immediately after migrating:
class OldFoo(models.Model)
field = models.BooleanField()
@property
def renamed_field(self):
return self.field
@renamed_field.setter
def renamed_field(self, value):
self.field = value
obsolete_field = models.BooleanField()
class Meta:
abstract = True
class NewFoo(models.Model)
renamed_field = models.BooleanField()
class Meta:
abstract = True
if waffle.switch_is_active('my_feature_switch'):
foo_model = NewFoo
else:
foo_model = OldFoo
class Foo(widget_model_model):
pass
I hope this shows the direction of a possible solution. It needs another deploy at some point to clean this up (basically renaming NewFoo
to Foo
and removing everything else).
The problem with the solution above is that we would need to restart all instances to respect the new waffle switch value. Restarting all servers is problematic. Preferably it respects a condition (waffle switch) during runtime.
We're on Django==1.6, South==1.0.
Completely different solution, rename object field, but specify old database column name using db_column
parameter.
class Foo(models.Model)
renamed_field = models.BooleanField(db_column='obsolete_field')
No migrations required.