2008-08-30 62 views
59

我正在考虑使用Django作为我开始的项目(fyi,基于浏览器的游戏),我最喜欢的功能之一是使用syncdb自动创建数据库表基于我定义的Django模型(我似乎无法在其他任何框架中找到的功能)。 我已经想这是好得是真实的,当我看到这个在documentation在Django中更改数据库表

执行syncdb不会改变现有的表

执行syncdb只会创造尚未安装哪些车型表。它永远不会发出ALTER TABLE语句来匹配安装后对模型类所做的更改。更改模型类和数据库架构往往涉及某种形式的模糊,在这种情况下,Django的必须在正确的变化作出猜测。在这个过程中,关键数据可能会丢失。

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

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

我想知道什么是做到这一点的最好办法。想到两种解决方案:

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

有什么想法?

回答

59

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

编辑:嘿,这里来dmigrations

UPDATE:既然这个答案最初写,django-evolutiondmigrations兼得不再积极开发和South已成为Django的架构迁移的事实标准。南部的部分甚至可能会在下一个版本或两个版本中集成到Django中。

UPDATE:根据南(由安德鲁·戈德温,南方的作者撰写)到架构的迁移框架包含在Django 1.7+。

+1

django-evolution似乎工作正常,谢谢!值得指出的是,必须从头开始使用它(它不计算来自现有SQL的必要更改)。 – gatoatigrado 2009-09-07 18:57:17

9

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

的灯具,是包含数据库的序列化内容的文件的集合。所以,它就像具有数据库的备份,但因为它的东西Django是意识到这一点更容易使用,将有额外的好处,当你来到做这样的事情的单元测试。

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

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

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

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

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

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

+0

对于简单的演化,例如添加,删除或重命名字段,django-evolution对我而言效果很好。有时我必须添加一个我不想在模型中指定的默认值(而是告诉django-evolution只是为现有字段设置),但除此之外 - 没有抱怨。 – 2009-07-11 11:30:28

3

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

2

到目前为止,在我的公司我们已经使用了手动方法。最适合你的是非常依赖你的开发风格。

我们在生产系统中通常没有太多的模式更改,并且从开发到生产服务器的部署也有所规范。无论何时我们推出(每年10-20次),我们会对当前和即将到来的生产分支进行填写比较,以检查所有代码并注意生产服务器上必须更改的内容。所需的更改可能是其他依赖项,对设置文件的更改以及对数据库的更改。

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

2

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

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

我已经做了这样很多次,这是非常灵活的,允许你在表中留下的数据,同时从模型中移除。

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

2

Django 1.7(当前正在开发中)是adding native support用于模式迁移manage.py migratemanage.py makemigrationsmigrate弃用syncdb)。