在Django中更改数据库表

时间:2020-03-05 18:45:26  来源:igfitidea点击:

我正在考虑将Django用于我正在启动的项目(fyi,一个基于浏览器的游戏),而我最喜欢的功能之一是使用syncdb来基于我创建的Django模型自动创建数据库表定义(我在其他任何框架中都找不到的功能)。
当我在文档中看到以下内容时,我已经认为这太好了,无法实现:

Syncdb will not alter existing tables
  
  syncdb will only create tables for models which have not yet been installed. It will never issue ALTER TABLE statements to match changes made to a model class after installation. Changes to model classes and database schemas often involve some form of ambiguity and, in those cases, Django would have to guess at the correct changes to make. There is a risk that critical data would be lost in the process.
  
  If you have made changes to a model and wish to alter the database tables to match, use the sql command to display the new SQL structure and compare that to your existing table schema to work out the changes.

似乎更改现有表将必须"手动"完成。

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

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

有任何想法吗?

解决方案

回答

手动执行SQL更改和转储/重新加载都是两个选项,但是我们可能还想签出一些Django的schema-evolution程序包。最成熟的选择是django-evolution和South。

编辑:嘿,移民来了。

更新:自从最初编写此答案以来,django-evolution和dmigrations都停止了积极的开发,而South已成为Django中架构迁移的实际标准。在下一两个版本中,South的某些部分甚至可以集成到Django中。

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

回答

一种实现方法是通过固定装置,特别是initial_data固定装置。

固定装置是包含数据库的序列化内容的文件的集合。因此,这就像有数据库的备份一样,但是Django意识到它更易于使用,并且在进行诸如单元测试之类的工作时会带来更多好处。

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

我们可以使用django-admin.py loaddata加载固定装置,但更重要的是,如果固定装置具有类似initial_data.json的名称,则在执行syncdb时它将自动加载,从而省去了自己导入固定装置的麻烦。 。

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

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

在开发过程中对数据库进行少量更改时,这种方法最有效。为了更新生产数据库,手动生成的SQL脚本通常效果最好。

回答

我一直在使用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)
    ]

如果我有更多的指纹和更改,我将对其进行重构。在此之前,使其变得更清洁将浪费其他时间的开发时间。

编辑:鉴于我还是手动构建更改,因此下次我将尝试迁移。

回答

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

回答

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

另外,地图上还有两个新项目:Simplemigrations和Migratory。

回答

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

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

这对我们来说非常有效。将其全部自动化是一个利基的愿景,但是对我们来说困难的是,也许我们可以管理迁移,但无论依赖关系如何,我们仍然需要处理其他库,服务器。