62

我正在考虑将 Django 用于我正在启动的项目(仅供参考,一个基于浏览器的游戏),我最喜欢的功能之一是使用syncdb我定义的 Django 模型自动创建数据库表(a我似乎在任何其他框架中都找不到的功能)。当我在文档中看到这一点时,我已经认为这太好了,难以置信:

Syncdb 不会改变现有的表

syncdb 只会为尚未安装的模型创建表。它永远不会发出 ALTER TABLE 语句来匹配安装后对模型类所做的更改。对模型类和数据库模式的更改通常涉及某种形式的歧义,在这些情况下,Django 必须猜测要做出的正确更改。在此过程中存在丢失关键数据的风险。

如果您对模型进行了更改并希望更改数据库表以匹配,请使用 sql 命令显示新的 SQL 结构并将其与现有表模式进行比较以计算出更改。

似乎必须“手动”更改现有表。

我想知道的是最好的方法。想到了两个解决方案:

  • 正如文档所建议的,在数据​​库中手动进行更改;
  • 备份数据库,擦除它,再次创建表(使用syncdb,因为现在它正在从头开始创建表)并导入备份的数据(如果数据库很大,这可能需要太长时间)

有任何想法吗?

4

7 回答 7

61

手动执行 SQL 更改和转储/重新加载都是选项,但您可能还想查看 Django 的一些模式演变包。最成熟的选择是django-evolutionSouth

编辑:嘿,这里来了 dmigrations

更新:由于最初编写了这个答案,django-evolutiondmigrations都停止了积极的开发,South已成为 Django 中模式迁移的事实标准。South 的部分内容甚至可能在下一两个版本中集成到 Django 中。

更新:基于 South 的模式迁移框架(由 South 的作者 Andrew Godwin 编写)包含在 Django 1.7+ 中。

于 2008-08-30T14:56:49.777 回答
17

如同一主题的其他答案中所述,请务必观看YouTube 上的DjangoCon 2008 Schema Evolution Panel 。

此外,地图上还有两个新项目:SimplemigrationsMigrator

于 2008-10-09T12:16:02.317 回答
9

做到这一点的一种好方法是通过固定装置,尤其是initial_data固定装置。

固定装置是包含数据库序列化内容的文件集合。因此,这就像备份数据库一样,但 Django 知道它更易于使用,并且在您进行单元测试之类的事情时会有额外的好处。

您可以使用当前在数据库中的数据创建夹具django-admin.py dumpdata。默认情况下,数据采用 JSON 格式,但也可以使用 XML 等其他选项。存储设备的好地方是fixtures应用程序目录的子目录。

你可以使用加载一个fixture,django-admin.py loaddata但更重要的是,如果你的fixture有一个名字initial_data.json,当你做a时它会自动加载syncdb,省去了你自己导入的麻烦。

另一个好处是,当您运行manage.py test单元测试时,临时测试数据库也将加载初始数据夹具。

当然,当您将属性添加到模型和列到数据库时,这将起作用。如果从数据库中删除一列,则需要更新固定装置以删除该列的数据,这可能并不简单。

这在开发过程中进行大量小的数据库更改时效果最佳。对于更新生产数据库,手动生成的 SQL 脚本通常效果最好。

于 2008-08-30T14:57:32.550 回答
4

我一直在使用 django-evolution。警告包括:

  • 它的自动建议已经烂透了;和
  • 它的指纹函数在不同平台上为同一个数据库返回不同的值。

也就是说,我发现自定义schema_evolution.py方法很方便。为了解决指纹问题,我建议使用如下代码:

BEFORE = 'fv1:-436177719' # first fingerprint
BEFORE64 = 'fv1:-108578349625146375' # same, but on 64-bit Linux
AFTER = 'fv1:-2132605944' 
AFTER64 = 'fv1:-3559032165562222486'

fingerprints = [
    BEFORE, AFTER,
    BEFORE64, AFTER64,
    ]

CHANGESQL = """
    /* put your SQL code to make the changes here */
    """

evolutions = [
    ((BEFORE, AFTER), CHANGESQL),
    ((BEFORE64, AFTER64), CHANGESQL)
    ]

如果我有更多的指纹和变化,我会重新考虑它。在那之前,让它更清洁会占用其他东西的开发时间。

编辑:鉴于无论如何我都在手动构建我的更改,我下次会尝试dmigrations 。

于 2008-09-11T02:44:47.623 回答
3

django-command-extensions是一个 django 库,它为 manage.py 提供了一些额外的命令。其中之一是 sqldiff,它应该为您提供更新到新模型所需的 sql。然而,它被列为“非常实验性”。

于 2008-09-11T23:33:07.000 回答
2

到目前为止,在我的公司中,我们一直使用手动方法。最适合您的方法很大程度上取决于您的开发风格。

我们通常在生产系统中没有太多架构更改,也没有从开发到生产服务器的某种形式化的部署。每当我们推出(每年 10-20 次)时,我们都会对当前和即将到来的生产分支进行填充差异,检查所有代码并注意生产服务器上必须更改的内容。所需的更改可能是附加依赖项、对设置文件的更改和对数据库的更改。

这对我们非常有效。让它全部自动化是一个利基愿景,但对我们来说很难——也许我们可以管理迁移,但我们仍然需要处理额外的库、服务器以及任何依赖项。

于 2009-01-04T14:26:54.233 回答
2

Django 1.7(目前正在开发中)正在使用和(弃用)添加对模式迁移的本机支持manage.py migratemanage.py makemigrationsmigratesyncdb

于 2013-12-17T17:23:14.397 回答