首页 文章

Django阻止远程数据库上的迁移

提问于
浏览
1

我有一个连接到两个数据库的Django应用程序 . 我的一个DB位于不同的( 生产环境 )服务器上 . 我想确保在开发我的应用程序时,我不会意外地在 生产环境 服务器上迁移模型 . 我的理解是这样的:假设我的settings.py DATABASES是这样的:

DATABASES = {
    'default': {},
    'remote_db': {
        'NAME'    : 'important_remote_db_name',
        'ENGINE'  : 'django.db.backends.mysql',
        'USER'    : 'someuser',
        'PASSWORD': 'somepass',
        'HOST'    : 'some.production.host.com',
        'PORT'    : '3306',
    },
    'myapp_db': {
        'NAME'    : 'my_app_db_name',
        'ENGINE'  : 'django.db.backends.mysql',
        'USER'    : 'localuser',
        'PASSWORD': 'localpassword'
    }
}

现在假设我还有一个名为RemoteDBRouter的路由器类 . 与所有路由器一样,该类将具有allow_migrate方法 . 请注意,远程数据库使用Django auth模型,因此User模型将具有app_label'auth',而远程DB也有自己的app_label'remoteapp'模型 . 有了这些信息,我看到了allow_migrate方法的两种可能性:

#OPTION 1
def allow_migrate(self, db, app_label, model_name=None, **hints):
    if app_label == 'auth' or app_label == 'remoteapp':
        return db == 'remote_db'
    return None

#OPTION 2
def allow_migrate(self, db, app_label, model_name=None, **hints):
    if app_label == 'auth' or app_label == 'remoteapp':
        return False
    return None

我应该使用哪一个?选项2更容易,因为它只是说我不应该迁移app_label表示模型来自远程数据库的任何模型 . 选项1进行额外的检查以查看db字段是否为'remote_db'(我假设我们需要检查'remote_db'而不是'remote_db_name') . 我使用哪一个是否重要?我担心如果我使用选项1并且db检查失败,该方法将返回None,然后Django代码将检查下一个路由器类,其中allow_migrate可能返回True .

1 回答

  • 2

    您希望 RemoteDBRouterremote_db 数据库具有权威性 . 您不希望从本地计算机控制其对 authremoteapp 或其他应用程序的迁移 . 其他数据库不一定由RemoteDBRouter控制 . 因此,您从:

    if db == 'remote_db':
            return False
    

    问题是,如果您希望在开发写入操作时有时将 authremoteapp 切换到本地,或者如果您只希望只读访问,那么这些表永远不需要在本地创建 . 然后你可以添加:

    if app_label == 'auth' or app_label == 'remoteapp':
            return False
    

    其他数据库的迁移可以由默认路由器或其他路由器控制:

    return None
    

    在本地创建 test database 的测试更复杂 .

    DATABASES = {
        'remote_db': {
            ...
            'HOST': 'some.production.host.com',
            'USER': 'some_readonly_user',   # read-only for security
            'TEST': {
                'HOST': 'localhost',
                ...
            }
        }
    }
    

    (可选)您还可以通过路由器规则支持对远程数据库的只读访问:

    def db_for_write(model, **hints):
        if model._meta.app_label in ('auth', 'remoteapp'):
            return 'myapp_db'  # or maybe the db 'default' where the model doesn't exist
    

    如果您错误地写作,则例外优于损害 生产环境 数据 . 路由器可以通过多种方式覆盖,例如:通过 using=db 参数或 .using(db) 方法 . 为安全起见,连接应由只读用户进行 .

相关问题