Django 防止远程数据库迁移
Django prevent migrations on remote database
我有一个连接到两个数据库的 Django 应用程序。我的一个数据库在不同的(生产)服务器上。我想非常确保在开发我的应用程序时,我不会不小心在生产服务器上迁移模型。我的理解是这样的:假设我的 settings.py 数据库是这样的:
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 的路由器 class。像所有路由器一样,class 将有一个方法 allow_migrate。请注意,远程数据库使用 Django 身份验证模型,因此用户模型将具有 app_label 'auth',远程数据库也有自己的模型 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 并且数据库检查失败,该方法将 return None 然后 Django 代码将检查下一个路由器 class 其中 allow_migrate可能 return 正确。
您希望 RemoteDBRouter
对 remote_db
数据库具有权威性。您不想控制它从本地计算机迁移到 auth
和 remoteapp
或其他应用程序。其他数据库不一定由 RemoteDBRouter 控制。因此你开始:
if db == 'remote_db':
return False
问题是,当您开发写操作时,您是否希望有时将 auth
和 remoteapp
切换到本地,或者您是否希望只有只读访问权限,并且永远不需要在本地创建这些表.然后你可以添加:
if app_label == 'auth' or app_label == 'remoteapp':
return False
其他数据库的迁移可以由默认路由器或其他路由器控制:
return None
在本地创建一个测试数据库测试比较复杂。
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)
方法。为了安全起见,连接应该由只读用户进行。
我有一个连接到两个数据库的 Django 应用程序。我的一个数据库在不同的(生产)服务器上。我想非常确保在开发我的应用程序时,我不会不小心在生产服务器上迁移模型。我的理解是这样的:假设我的 settings.py 数据库是这样的:
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 的路由器 class。像所有路由器一样,class 将有一个方法 allow_migrate。请注意,远程数据库使用 Django 身份验证模型,因此用户模型将具有 app_label 'auth',远程数据库也有自己的模型 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 并且数据库检查失败,该方法将 return None 然后 Django 代码将检查下一个路由器 class 其中 allow_migrate可能 return 正确。
您希望 RemoteDBRouter
对 remote_db
数据库具有权威性。您不想控制它从本地计算机迁移到 auth
和 remoteapp
或其他应用程序。其他数据库不一定由 RemoteDBRouter 控制。因此你开始:
if db == 'remote_db':
return False
问题是,当您开发写操作时,您是否希望有时将 auth
和 remoteapp
切换到本地,或者您是否希望只有只读访问权限,并且永远不需要在本地创建这些表.然后你可以添加:
if app_label == 'auth' or app_label == 'remoteapp':
return False
其他数据库的迁移可以由默认路由器或其他路由器控制:
return None
在本地创建一个测试数据库测试比较复杂。
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)
方法。为了安全起见,连接应该由只读用户进行。