在Django中更改数据库表

我正在考虑使用Django开始一个项目(fyi,一个基于浏览器的游戏),我最喜欢的一个function是使用syncdb自动创build基于我定义的Django模型的数据库表我似乎无法在其他任何框架中find这个function)。 当我在文档中看到这个时,我已经认为这太好了,

Syncdb不会改变现有的表格

syncdb只会为尚未安装的模型创build表格。 它永远不会发出ALTER TABLE语句来匹配安装后对模型类所做的更改。 模型类和数据库模式的变化通常会涉及某种forms的模糊性,在这种情况下,Django将不得不猜测正确的变化。 关键数据在这个过程中可能会丢失。

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

似乎改变现有的表格将不得不“手工”完成。

我想知道的是做到这一点的最好方法。 想到两个解决scheme:

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

有任何想法吗?

正如同一主题的其他答案中所指出的,一定要在YouTube上观看DjangoCon 2008 Schema Evolution Panel 。

此外,在地图上的两个新项目: 简单 迁移和迁徙 。

手动执行SQL更改和dump / reload都是选项,但是您也可能想要查看Django的一些schema-evolution软件包。 最成熟的select是django-evolution和South 。

编辑 :嘿,这里是移民 。

更新 :由于这个答案是最初写的, django-evolution和dmigrations都停止了积极的发展,而南方已经成为Django模式迁移的事实上的标准。 南部的部分甚至可能在下一个版本中被整合到Django中。

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

一个好办法是通过灯具,特别是initial_data灯具。

夹具是包含数据库的序列化内容的文件的集合。 所以这就像是对数据库进行备份,但是因为它是Django意识到它更容易使用,并且当你来做unit testing之类的时候会有额外的好处。

您可以使用django-admin.py dumpdata从当前数据库中的数据创build一个夹具。 默认情况下,数据采用JSON格式,但其他选项(如XML)可用。 存储灯具的好地方是你的应用程序目录的fixtures子目录。

您可以使用django-admin.py loaddata加载修复django-admin.py loaddata但更重要的是,如果您的fixture具有像initial_data.json这样的名称,那么在执行syncdb时将自动加载它,从而节省了自己导入它的麻烦。

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

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

这在开发过程中做很多小的数据库更改时效果最好。 为了更新生产数据库,手动生成的SQL脚本通常可以发挥最佳效果。

我一直在使用Django的进化。 注意事项包括:

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

这就是说,我发现自定义schema_evolution.py方法得心应手。 要解决指纹问题,我build议像这样的代码:

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

如果我有更多的指纹和变化,我会重新考虑它。 在那之前,把它变得更加清洁就是从别的东西上偷取开发时间。

编辑:鉴于我手动构build我的变化无论如何,我会尝试下一次移民 。

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

到目前为止,在我们公司,我们已经使用了手动方法。 什么最适合你,取决于你的发展风格。

在生产系统中,我们通常没有太多的模式改变,并且从开发到生产服务器有一些正式的推出。 每当我们推出(每年10-20次),我们会对当前和即将到来的生产分公司进行填写比较,检查所有代码,并注意生产服务器上的哪些内容需要更改。 所需的更改可能是其他依赖项,对设置文件的更改和对数据库的更改。

这对我们很好。 拥有全部自动化是一个利基的愿景,但对我们来说很困难 – 也许我们可以pipe理迁移,但是我们仍然需要处理额外的库,服务器,不pipe依赖关系。

Django书籍解释了如何手工完成。

http://www.djangobook.com/en/2.0/chapter10/

我这样做了很多次,而且非常灵活,可以在将数据从模型中删除的同时将数据保留在表中。

我最近开始使用南方。 它似乎有点不灵活(或者我只是需要阅读文档更多),但可以节省您一些打字。 有时你设法让它与数据库不同步,这是一场噩梦。 只要你继续使用它,它似乎会很好。它似乎把模型和实际的数据库连接在一起,根据你的情况,这可能会也可能不是一件好事

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