【问题标题】:How do I support an old and new database scheme at the same time in Django?如何在 Django 中同时支持新旧数据库模式?
【发布时间】:2014-11-10 01:28:00
【问题描述】:

现状,遗留问题:

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。

【问题讨论】:

  • 你熟悉dynamic models吗?他们可能会有所帮助......
  • 感谢您的回复。我认为本指南已经过时,我可能会沿着这条路线进入一个痛苦的世界。这意味着我必须以动态的方式重写我的整个模型。我的 OP 中显示的示例是一个非常胖模型的简化版本。
  • 是的,它已经过时了,但那里有一个指向同一主题的very detailed and updated SO answer 的链接。我会尝试考虑另一种方法(顺便说一句,vartec 的回答没有帮助吗?)
  • 还有——为什么不添加新模型,然后在views 中添加切换器,然后你可以在哪里做import newFoo as Foo?另外,this might be helpful
  • 是的,我接受并实施了 Vartec 的解决方案,但我总是乐于了解解决问题的其他方法,以添加到我的问题解决工具箱中。我很高兴我了解了动态模型,它们总有一天会派上用场。

标签: django django-models django-south


【解决方案1】:

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

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

无需迁移。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-25
    • 1970-01-01
    • 2011-03-28
    • 2021-12-29
    • 2010-12-31
    • 1970-01-01
    • 2019-08-29
    • 2020-01-22
    相关资源
    最近更新 更多