94 lines
3.1 KiB
Python
94 lines
3.1 KiB
Python
"""gvsdsdk.db_router — 开箱即用的 SAAS 数据库路由器
|
||
|
||
子服务器只需在 settings.py 中配置:
|
||
DATABASE_ROUTERS = ['gvsdsdk.db_router.SAASDatabaseRouter']
|
||
|
||
即可自动将 gvsdsdk 的所有模型路由到 SAAS 主库。
|
||
|
||
配置项(settings.py):
|
||
GVSDSDK_SAAS_DB_ALIAS = 'saas' # SAAS 数据库别名,默认 'saas'
|
||
GVSDSDK_SAAS_READ_ONLY = True # 子服务器是否只读,默认 True
|
||
"""
|
||
|
||
|
||
class SAASDatabaseRouter:
|
||
"""SAAS 模型数据库路由器——将 gvsdsdk 模型路由到 SAAS 主库
|
||
|
||
用法:
|
||
# settings.py
|
||
DATABASES = {
|
||
'default': { ... }, # 本地数据库
|
||
'saas': { # SAAS 主库
|
||
'ENGINE': 'django.db.backends.mysql',
|
||
'NAME': 'Users',
|
||
...
|
||
},
|
||
}
|
||
DATABASE_ROUTERS = ['gvsdsdk.db_router.SAASDatabaseRouter']
|
||
|
||
# 可选配置
|
||
GVSDSDK_SAAS_DB_ALIAS = 'saas' # 默认 'saas'
|
||
GVSDSDK_SAAS_READ_ONLY = True # 默认 True(子服务器只读)
|
||
"""
|
||
|
||
# gvsdsdk 内所有模块前缀
|
||
_GVSDSDK_MODULES = frozenset({
|
||
'gvsdsdk.models',
|
||
'gvsdsdk.commission.models',
|
||
'gvsdsdk.payment.models',
|
||
})
|
||
|
||
# gvsdsdk 内所有 app_label
|
||
_GVSDSDK_APP_LABELS = frozenset({
|
||
'gvsdsdk',
|
||
})
|
||
|
||
def _get_saas_db(self):
|
||
from django.conf import settings
|
||
return getattr(settings, 'GVSDSDK_SAAS_DB_ALIAS', 'saas')
|
||
|
||
def _is_read_only(self):
|
||
from django.conf import settings
|
||
return getattr(settings, 'GVSDSDK_SAAS_READ_ONLY', True)
|
||
|
||
def _is_gvsdsdk_model(self, model):
|
||
"""判断模型是否属于 gvsdsdk"""
|
||
# 按模块路径判断
|
||
module = getattr(model, '__module__', '')
|
||
if module in self._GVSDSDK_MODULES or module.startswith('gvsdsdk.'):
|
||
return True
|
||
# 按 app_label 判断
|
||
app_label = getattr(model._meta, 'app_label', '')
|
||
if app_label in self._GVSDSDK_APP_LABELS:
|
||
return True
|
||
return False
|
||
|
||
def db_for_read(self, model, **hints):
|
||
if self._is_gvsdsdk_model(model):
|
||
return self._get_saas_db()
|
||
return None
|
||
|
||
def db_for_write(self, model, **hints):
|
||
if self._is_gvsdsdk_model(model):
|
||
if self._is_read_only():
|
||
raise RuntimeError(
|
||
"gvsdsdk SAAS database is read-only for sub-servers. "
|
||
"Set GVSDSDK_SAAS_READ_ONLY=False to allow writes."
|
||
)
|
||
return self._get_saas_db()
|
||
return None
|
||
|
||
def allow_relation(self, obj1, obj2, **hints):
|
||
# 允许同一数据库内的关联
|
||
db1 = self.db_for_read(obj1.__class__)
|
||
db2 = self.db_for_read(obj2.__class__)
|
||
if db1 and db2 and db1 == db2:
|
||
return True
|
||
return None
|
||
|
||
def allow_migrate(self, db, app_label, model_name=None, **hints):
|
||
# gvsdsdk 模型不迁移(managed=False 或由主服务器管理)
|
||
if app_label in self._GVSDSDK_APP_LABELS:
|
||
return db != self._get_saas_db()
|
||
return None
|