在 Django 中使迁移有条件
Posted
技术标签:
【中文标题】在 Django 中使迁移有条件【英文标题】:Make Migration Conditional in Django 【发布时间】:2015-10-28 03:21:53 【问题描述】:具体用例是:
A Django module 想在迁移期间创建扩展。如果 用于运行迁移的数据库用户不是超级用户,这 失败。
有几种方法可以解决这个问题,一种方法是(假设地)检查迁移文件是否安装了扩展,如果没有安装则只运行该 SQL 代码。
然而,经过一些研究,似乎 Django 的RunSQL
无法返回结果,随后根据先前操作的结果排除操作是不可能的。还有其他方法可以实现这一目标吗? (例如子类化RunSQL
?)
任何基于 Django 迁移、Django 设置或 Postgres 内部的解决方案(只有在特定条件为真时才能实现运行 CREATE EXTENSION
的一条 SQL 语句)都可以。
(请注意,我提到 django-pgcrypto-fields 只是为了说明。我很想知道这种解决方案是否普遍存在。)
编辑回答 Anentropic 的评论:
运行test
或jenkins
命令时,该解决方案必须有效。这意味着,手动调用--fake-initial
或类似方法来避免运行此迁移不是一种选择。如果你能解释如何使test
伪造某些迁移,这是非常受欢迎的。
我目前的解决方案是将以下内容添加到settings
:
MIGRATION_MODULES =
'pgcrypto_fields': 'do-not-run-migrations'
但这将禁用所有有问题的迁移,而不仅仅是有问题的迁移。在这种情况下,它可能会起作用,但我认为这是一种幸运且丑陋的解决方法。
【问题讨论】:
模块需要扩展才能工作,所以你需要找到一种方法来创建扩展。我建议以管理员用户身份创建扩展程序,然后 fake 有问题的迁移 @Anentropic 感谢您的建议。不幸的是,这不适用于manage.py test
,恕我直言。我已经编辑了我的问题以回答您的评论。
如果是用于运行测试,我建议使用不同的数据库设置进行测试,您的 django db 用户可以在测试数据库上获得管理员访问权限
我知道还有其他方法可以解决具体的用例。但是我真正想知道是否有一种方法可以根据某些条件运行迁移操作(无论是通过迁移文件中的代码,还是通过 SQL 代码本身,或者通过 Django 设置)。我刚刚添加了用例作为示例。
如果你编写了迁移,你可以有条件地做一些事情,我想这对于 3rd 方迁移将是困难/不可能的
【参考方案1】:
实际上,Django 的HStoreExtension 只在必要时运行。但当然,它仍然需要超级用户访问权限。对于 pgcrypto,可以创建一个类似于 HStoreExtension 的类。
使其在测试中运行的设置仍需要超级用户访问权限,因此设置必须如下所示:
INSTALLED_APPS = (
...
'django.contrib.postgres',
...
)
if sys.argv[1] in ['test', 'jenkins']:
# Install extension hstore (requires superuser)
INSTALLED_APPS = ('test_init',) + INSTALLED_APPS
# a superuser
DATABASES["default"]["USER"] = 'xxx'
DATABASES["default"]["PASSWORD"] = 'xxx'
'test_init' django 应用仅包含所需的 __init.py__
和带有以下文件 0001_initial.py
的迁移模块:
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.contrib.postgres.operations import HStoreExtension
from django.db import migrations
class Migration(migrations.Migration):
run_before = [
('some_app_that_requires_hstore', '0001_initial'),
]
operations = [
HStoreExtension(),
]
实际上不需要检查测试模式(通过sys.argv
)来进行迁移。如上所述,HStoreExtension 对错误保持沉默。因此,即使您在没有超级用户的情况下在生产环境中运行migrate
,它也不会失败,无论是否安装了 hstore。查看它的源代码。
另见Django's documentation of HStoreField。
【讨论】:
以上是关于在 Django 中使迁移有条件的主要内容,如果未能解决你的问题,请参考以下文章