Web开发中通常在本地进行开发,然后将代码部署到服务器上,这里就涉及本地环境和服务器环境数据库的配置。
我使用的服务器环境是新浪云(SAE),代码部署是通过git上传到指定的GIT仓库。
要切换两个数据库配置选项,最笨的办法是部署代码时设置为服务器数据库环境,本地测试时再把配置改回本地数据库环境。
这样就面临一个开发效率问题:如何在使用一套代码的情况下,让本地和服务器自动选择正确的数据库配置呢?
记得之前在浏览Django官网时有看到multi database配置,估计跟这有关系,上去找一下,果然看到有数据库路由设置。
一个Django项目可以设置多个数据库,比如设置数据库读写分离需要设置主从数据库,而究竟选择哪个数据库需要有负责路由的类来决定。
在settings.py中,DATABASES 设置数据库的配置表,而 DATABASE_ROUTERS 则设置路由数据库的类。
指定的Router类可以实现 db_for_read,db_for_write等方法
参考官网说明:https://docs.djangoproject.com/en/1.8/topics/db/multi-db/#topics-db-multi-db-routing
如何区分当前环境是本地还是服务器呢?
@settings.py
我使用的服务器环境是新浪云(SAE),代码部署是通过git上传到指定的GIT仓库。
要切换两个数据库配置选项,最笨的办法是部署代码时设置为服务器数据库环境,本地测试时再把配置改回本地数据库环境。
这样就面临一个开发效率问题:如何在使用一套代码的情况下,让本地和服务器自动选择正确的数据库配置呢?
记得之前在浏览Django官网时有看到multi database配置,估计跟这有关系,上去找一下,果然看到有数据库路由设置。
一个Django项目可以设置多个数据库,比如设置数据库读写分离需要设置主从数据库,而究竟选择哪个数据库需要有负责路由的类来决定。
在settings.py中,DATABASES 设置数据库的配置表,而 DATABASE_ROUTERS 则设置路由数据库的类。
指定的Router类可以实现 db_for_read,db_for_write等方法
参考官网说明:https://docs.djangoproject.com/en/1.8/topics/db/multi-db/#topics-db-multi-db-routing
如何区分当前环境是本地还是服务器呢?
有几种方法:
1.使用导入服务器特有模块来判断,比如sae环境,如果导入sae模块成功说明是在服务器环境了。
@settings.py
# 数据库配置表
DATABASES = {
# 默认使用本地数据库
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'django_gallery',
'USER': 'xxx',
'PASSWORD': 'xxx',
'HOST': '127.0.0.1',
'PORT': '3306',
},
# SAE数据库配置
'remote': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'xxx',
'USER': 'xxx',
'PASSWORD': 'xxx',
'HOST': 'w.rdc.sae.sina.com.cn',
'PORT': '3307',
}
}
#设置路由类
DATABASE_ROUTERS = ['Gallery.db_router.LocalRemoteRouter']
@db_router.py
import logging
logger = logging.getLogger('items')
class LocalRemoteRouter(object):
"""
A router to decide select local or remote sae db
"""
init = True
local = True
def is_local_env(self):
local_env = False
try:
import sae
except(ImportError):
local_env = True
logger.info("import sae error")
else:
local_env = False
logger.info("import sae ok")
return local_env
def db_for_read(self, model, **hints):
if self.init == True:
self.init = False
self.local = self.is_local_env()
if self.local == True:
return 'default'
else:
return 'remote'
def db_for_write(self, model, **hints):
if self.init == True:
self.init = False
self.local = self.is_local()
if self.local == True:
return 'default'
else:
return 'remote'
2.使用os模块变量判断
@db_router.py
import os
class LocalRemoteRouter(object):
def db_for_read(self, model, **hints):
if 'SERVER_SOFTWARE' in os.environ:
# SAE
return 'remote'
else:
# Local
return 'default'
def db_for_write(self, model, **hints):
if 'SERVER_SOFTWARE' in os.environ:
# SAE
return 'remote'
else:
# Local
return 'default'
部署代码到服务器上,打开首页,可以看到熟悉的画面了!
这样不论以后在本地还是服务器测试,数据库配置的代码不需要再改变!
==================================== 更新 ===============================================
通常本地与服务器环境切换配置的不止数据库,还有其他参数,于是想到创建个文件专门处理:
@config.py
import os
import logging
logger = logging.getLogger('items')
#本地配置参数
class Local():
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'xxx',
'USER': 'xxx',
'PASSWORD': 'xxx',
'HOST': '127.0.0.1',
'PORT': '3306',
},
}
#服务器配置参数
class Remote():
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'xxx',
'USER': 'xxx',
'PASSWORD': 'xxx',
'HOST': 'w.rdc.sae.sina.com.cn',
'PORT': '3307',
}
}
class MyConfig():
__conf = None
__is_remote = 'SERVER_SOFTWARE' in os.environ
def is_remote_env(self):
return self.__is_remote
def get_config(self):
if self.__conf == None:
if self.__is_remote:
logger.info("set remote config")
self.__conf = Remote()
else:
logger.info("set local config")
self.__conf = Local()
return self.__conf
@settings.py
使用MyConfig得到正确的配置对象,访问正确的配置参数
from config import MyConfig
my_config = MyConfig()
MEDIA_URL = my_config.get_config().MEDIA_URL
MEDIA_ROOT = my_config.get_config().MEDIA_ROOT
DATABASES = my_config.get_config().DATABASES
#DATABASE_ROUTERS = ['Gallery.db_router.LocalRemoteRouter']
该方法没有使用数据库Router,因此把原来设置的 DATABASE_ROUTERS 注释掉。
通过这种方法,两种环境下分别设置各自的参数即可。