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()

      

Required situation:

class Foo(models.Model)
    renamed_field = models.BooleanField()

      

No problems. South can handle migration with db.rename_column

and db.deletecolumn

.

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 my_feature_switch

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 NewFoo

to Foo

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.

+3


source to share


1 answer


Completely different solution, rename the object field but provide the name of the old database column using the parameter db_column

.

class Foo(models.Model)
    renamed_field = models.BooleanField(db_column='obsolete_field')

      



No migration required.

+2


source







All Articles