115

Django 1.7引入了数据库迁移

在 Django 1.7 中运行单元测试时,它会强制执行migrate,这需要很长时间。所以我想跳过 django 迁移,并在最终状态下创建数据库。

我知道忽略迁移可能是一种不好的做法,因为这部分代码不会被测试。但事实并非如此:我正在 CI 测试服务器 (jenkins) 中运行完整的迁移。我只想跳过本地测试中的迁移,其中速度很重要。


一些上下文:

在 Django 1.6之前,使用 South 时,我使用了SOUTH_TESTS_MIGRATE设置:

默认情况下,如果 South 的 syncdb 命令在非交互模式下运行,它也会应用迁移,其中包括运行测试时 - 每次运行测试时它都会运行每个迁移。

如果您希望测试运行程序使用 syncdb 而不是 migrate - 例如,如果您的迁移花费的时间太长而无法应用 - 只需在 settings.py 中设置 SOUTH_TESTS_MIGRATE = False。

但是,syncdb不再存在,现在它是migrate

从 Django 1.8开始,我将使用--keepdb参数:

--keepdb 选项可用于在测试运行之间保留测试数据库。这具有跳过创建和销毁操作的优点,这大大减少了运行测试的时间,尤其是大型测试套件中的测试。如果测试数据库不存在,它将在第一次运行时创建,然后为每次后续运行保留。在运行测试套件之前,任何未应用的迁移也将应用于测试数据库。

所以这个问题仅限于 Django 1.7。

4

7 回答 7

82

看看这个由 Bernie Sumption 发布到 Django 开发者邮件列表的解决方法:

如果 makemigrations 尚未运行,“migrate”命令会将应用程序视为未迁移,并直接从模型创建表,就像 syncdb 在 1.6 中所做的那样。我为单元测试定义了一个名为“settings_test.py”的新设置模块,它从主设置模块导入 * 并添加以下行:

MIGRATION_MODULES = {“myapp”:“myapp.migrations_not_used_in_tests”}

然后我运行这样的测试:

DJANGO_SETTINGS_MODULE="myapp.settings_test" python manage.py test

这些傻瓜迁移到认为应用程序未迁移,因此每次创建测试数据库时都会反映models.py的当前结构。

在 Django 1.9 中,这种情况有所改善,您可以将值设置为None

MIGRATION_MODULES = {“myapp”:无}

于 2014-08-12T14:50:19.007 回答
76

这是我的设置文件的结尾:

class DisableMigrations(object):

    def __contains__(self, item):
        return True

    def __getitem__(self, item):
        return None


TESTS_IN_PROGRESS = False
if 'test' in sys.argv[1:] or 'jenkins' in sys.argv[1:]:
    logging.disable(logging.CRITICAL)
    PASSWORD_HASHERS = (
        'django.contrib.auth.hashers.MD5PasswordHasher',
    )
    DEBUG = False
    TEMPLATE_DEBUG = False
    TESTS_IN_PROGRESS = True
    MIGRATION_MODULES = DisableMigrations()

基于这个片段

我仅在测试运行时才禁用迁移

于 2015-02-17T11:20:14.423 回答
33

django-test-without-migrations添加一个--nomigrations标志到manage.py test. 奇迹般有效。

于 2015-03-11T17:32:37.283 回答
3

更新:没关系,此更改在 1.10 最终版发布之前已恢复。希望它会在未来的版本中回归。


请注意,从 Django 1.10 开始,这可以通过测试数据库设置来控制。

迁移

默认:True

如果设置为False,Django 将不会使用迁移来创建测试数据库。

于 2016-07-09T08:19:05.563 回答
3

我只是想出如何在 django 1.10 之后禁用迁移,可能对某人有帮助。这是git的链接

class DisableMigrations(dict):
    def __contains__(self, item):
        return True

    def __getitem__(self, item):
        return None

DATABASES = DisableMigrations()

MIGRATION_MODULES = DisableMigrations()

django 1.10 的迁移有两个部分,请查看load_diskrecorder

load_disk添加的应用程序迁移模型的部分和数据库连接INSTALL_APP 的部分recorder对于1.9之前的版本,我们需要MIGRATION_MODULES={'do.not.migrate':'notmigrations'}在运行测试时设置现在我们需要将它设置为无,MIGRATION_MODULES={'do.not.migrate':None} 所以如果我们不想为任何应用程序进行迁移,只需扩展一个dict并返回None函数getitem,然后在at上做同样DATABASES的事情,这是你需要做的正确的事情

PS:对于命令,您需要在PPS--setting=module.path.settings_test_snippet之后指定如果您正在使用,请不要在 处设置 选项,只需在自定义设置处添加路径即可。就好了!!test pycharm--settingsRun/Debug configurationssettings_test_snippet.py

请享用

于 2017-12-13T20:13:41.877 回答
2

https://gist.github.com/apollovy/22826f493ad2d06d9a9a22464730ce0b

MIGRATION_MODULES = {
    app[app.rfind('.') + 1:]: 'my_app.migrations_not_used_in_tests'
    for app in INSTALLED_APPS
}
于 2016-04-05T14:48:41.887 回答
2

对于 django 1.9 及更高版本,Guillaume Vincent 的答案不再起作用,所以这是一个新的解决方案:

我在我的设置文件中使用这个片段,在定义之后INSTALLED_APPS

if os.environ.get('TESTS_WITHOUT_MIGRATIONS', False):
    MIGRATION_MODULES = {
        app.split('.')[-1]: None for app in INSTALLED_APPS
    }

它遍历所有已安装的应用程序并将每个应用程序标记为没有迁移模块。有关更多信息,请参阅django 文档

使用此代码段,您可以运行测试,设置环境变量TESTS_WITHOUT_MIGRATIONS,例如:

TESTS_WITHOUT_MIGRATIONS=1 ./manage.py test
于 2017-04-05T13:37:30.067 回答