django多数据库操作
1. 读写分离
- 192.168.1.2 default 主数据库负责写入
- 192.168.1.3 slave 从数据库负责读取
2. 生成数据库表
python manage.py makemigrations
分别迁移到主从数据库
python manage.py migrate --database=default
python manage.py migrate --database=slave
多个app分表:分app操作数据库 假设app01对应数据库default,app02对应数据库slave
python manage.py makemigrations
python manage.py migrate app01 --database=default
python manage.py migrate app02 --database=slave
3. 开发时手动选择使用数据库
models.UserInfo.objects.using("default").create(title="admin")
models.UserInfo.objects.using("slave").all()
4. 多数据库,多app操作配置
settings.py中增加数据库配置
DATABASE_ROUTERS = ['KPIBackendSys.database_router.DatabaseAppsRouter'] # 读写文件路径
DATABASE_APPS_MAPPING = {
'app01': 'default',
'app02': 'slave',
}
DATABASES = {
# 默认AI数据库
'default': {
'ENGINE': 'mssql', # 要连接的 数据库类型
# 'ENGINE': 'sql_server.pyodbc', # 要连接的 数据库类型
'NAME': db1, # 要连接的 数据库名
'HOST': host, # 要连接的远程数据库的 ip地址
'PORT': port, # 数据库连接端口,mysql默认3306
'USER': user, # 数据库已有用户名
'PASSWORD': pwd, # 数据库已有用户密码
'OPTIONS': {
'driver': 'ODBC Driver 17 for SQL Server',
'MARS_Connection': True,
},
},
'slave': {
'ENGINE': 'mssql',
# 'ENGINE': 'sql_server.pyodbc', # 要连接的 数据库类型
'NAME': db2,
'HOST': host, # 要连接的远程数据库的 ip地址
'PORT': port, # 数据库连接端口,mysql默认3306
'USER': user, # 数据库已有用户名
'PASSWORD': pwd, # 数据库已有用户密码
'OPTIONS': {
'driver': 'ODBC Driver 17 for SQL Server',
# 'MARS_Connection': True,
},
},
}
在settings.py同级目录下增加database_router.py文件
database_router.py
class DatabaseAppsRouter(object):
def db_for_read(self, model, **hints):
# 判断模型类的元类中的app_label
if model._meta.app_label in DATABASE_MAPPING:
return DATABASE_MAPPING[model._meta.app_label]
return None
# 或直接判断并返回数据库
if model._meta.app_label == 'app01':
return default
if model._meta.app_label == 'app02':
return slave
def db_for_write(self, model, **hints):
"""
Point all write operations to the specific database.
"""
if model._meta.app_label in DATABASE_MAPPING:
return DATABASE_MAPPING[model._meta.app_label]
return None
# 或直接判断并返回数据库
if model._meta.app_label == 'app01':
return default
if model._meta.app_label == 'app02':
return slave
def allow_relation(self, obj1, obj2, **hints):
"""
Allow any relation between apps that use the same database.
"""
db_obj1 = DATABASE_MAPPING.get(obj1._meta.app_label)
db_obj2 = DATABASE_MAPPING.get(obj2._meta.app_label)
if db_obj1 and db_obj2:
if db_obj1 == db_obj2:
return True
else:
return False
return None
def allow_syncdb(self, db, model):
"""
Make sure that apps only appear in the related database.
"""
if db in DATABASE_MAPPING.values():
return DATABASE_MAPPING.get(model._meta.app_label) == db
elif model._meta.app_label in DATABASE_MAPPING:
return False
return None
def allow_migrate(self, db, app_label, model=None, **hints):
"""
Make sure the auth app only appears in the 'auth_db' database.
app_label, 表示使用的数据库别名
"""
if db in DATABASE_MAPPING.values():
# 允许迁移到auth_db
return DATABASE_MAPPING.get(app_label) == db
elif app_label in DATABASE_MAPPING:
return False
# 不允许迁移
return None
5. 同一个app下的模型存储在不同的数据库
使用database_router.py中的allow_migrate方法, 读写操作同样需要指定数据库
class DatabaseAppsRouter(object):
def db_for_read(self, model, **hints):
# 判断模型类的元类中的app_label
# 或直接判断并返回数据库
if model._meta.model_name in [model1, model2]:
return default
if model._meta.model_name in [model3, model3]:
return slave
def db_for_write(self, model, **hints):
# 或直接判断并返回数据库
if model._meta.model_name in [model1, model2]:
return default
if model._meta.model_name in [model3, model3]:
return slave
def allow_migrate(self, db, app_label, model=None, **hints):
if db == 'default':
if model_name in ['model1', 'model2']:
return True
return False
if db == 'slave':
if model_name in ['model3', 'model4']:
return True
return False