如何在Django中同时支持新旧数据库方案?

时间:2014-09-16 10:27:33

标签: django django-models django-south

目前的情况,由遗产引起:

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

还没问题。 South可以使用db.rename_columndb.deletecolumn处理迁移。

问题:我们的Django应用程序在具有共享MySQL实例的多个实例上运行。当我们将代码部署到生产环境时,我们会在引导新实例时逐个用新实例替换旧实例。如果我们想要避免停机,那么应用模型需要支持新的数据库方案,这里有一个问题:,而实例也被替换为旧的数据库方案。

我们希望避免停机。

一个天真的解决方案是我们部署的两步方法,等到所有实例都被替换,迁移并在迁移后立即启用my_feature_switch

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

我希望这显示了可能解决方案的方向。它需要在某个时刻进行另一次部署来清理它(基本上将NewFoo重命名为Foo并删除其他所有内容。

上述解决方案的问题是我们需要重新启动所有实例以尊重新的华夫饼干开关值。重新启动所有服务器是有问题的。优选地,它在运行期间遵守条件(华夫饼开关)。

  • 有没有其他方法可以使模型有条件?
  • 或许是一种完全不同的方法来解决这个问题?可能是每个字段的条件db_column,例如?

我们在Django == 1.6,South == 1.0。

1 个答案:

答案 0 :(得分:2)

完全不同的解决方案,重命名对象字段,但使用db_column参数指定旧数据库列名。

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

无需迁移。