我有一个连接到两个数据库的Django应用程序。我的一个DB位于不同的(生产)服务器上。我想确保在开发我的应用程序时,我不会意外地在生产服务器上迁移模型。我的理解是这样的:假设我的settings.py DATABASES是这样的:
BigDecimal.compare
现在假设我还有一个名为RemoteDBRouter的路由器类。与所有路由器一样,该类将具有allow_migrate方法。请注意,远程数据库使用Django auth模型,因此用户模型将具有app_label' auth'并且远程数据库也有自己的app_label' remoteapp'。有了这些信息,我看到了allow_migrate方法的两种可能性:
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'
}
}
我应该使用哪一个?选项2更容易,因为它只是说我不应该迁移app_label表示模型来自远程数据库的任何模型。选项1进行额外的检查以查看db字段是否是' remote_db' (我假设我们需要检查' remote_db'而不是' remote_db_name')。我使用哪一个是否重要?我担心如果我使用选项1并且数据库检查失败,该方法将返回None,然后Django代码将检查下一个路由器类,其中allow_migrate可能返回True。
答案 0 :(得分:2)
您希望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)
方法。为安全起见,连接应由只读用户进行。