How can I maintain old and new database schema at the same time in Django?
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()
class Foo(models.Model) renamed_field = models.BooleanField()
No problems. South can handle migration with
Problem: Our Django application runs in multiple instances with a shared MySQL instance. When we deploy our code to production, we replace the old instances with new instances one by one as new instances are loaded. If we want to avoid downtime, the application models must support the new database schema, and here's the catch: and while the instances are being replaced by the old database schema as well.
We would like to avoid downtime.
A naive solution would be a two-step approach where we deploy, wait for all instances to be swapped out, migrate and enable
right after migration:
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
Hopefully this will show the direction of a possible solution. It will need a different deployment at some point (basically renaming
and removing everything else).
The problem with the above solution is that we will need to restart all instances to evaluate the new value of the waffle switch. Restarting all servers is problematic. Preferably it meets a condition (waffle switch) at runtime.
- Is there any other way to make the model conditional?
- Or maybe a completely different way to solve this problem? Maybe a conditional db_column for each field, for example?
We are on Django == 1.6, South == 1.0.
source to share