"""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