Django双库场景如何避免django_spanner全局修改AutoField行为
解决方案
核心思路是隔离两个数据库的模型配置,从根源阻断django_spanner的全局字段补丁对RDS侧表的影响,具体操作如下:
- 配置数据库路由,严格划分两个库的操作边界
新建路由文件db_router.py,明确指定使用Spanner的子应用所有读写、迁移操作都走Spanner库,其余应用走RDS(配置为default库),禁止跨库关联,避免操作串库:
在class AppDBRouter: def db_for_read(self, model, **hints): if model._meta.app_label == "你的Spanner子应用名称": return "spanner" return "default" def db_for_write(self, model, **hints): if model._meta.app_label == "你的Spanner子应用名称": return "spanner" return "default" def allow_relation(self, obj1, obj2, **hints): # 禁止跨库模型关联 if obj1._state.db == obj2._state.db: return True return False def allow_migrate(self, db, app_label, model_name=None, **hints): if app_label == "你的Spanner子应用名称": return db == "spanner" return db == "default"settings.py中注册路由:DATABASE_ROUTERS = ["你的项目名.db_router.AppDBRouter"] - 覆盖django_spanner的全局AutoField补丁
在settings.py中显式声明全局默认主键字段为RDS需要的顺序自增类型,直接覆盖django_spanner启动时注入的全局配置:
如果要彻底阻断补丁注入,可以自定义Spanner的应用配置,跳过修改全局字段的逻辑,替换掉默认的django_spanner注册项:DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
随后把# 新建custom_spanner_config.py from django_spanner.apps import DjangoSpannerConfig from django.conf import settings class FixedSpannerConfig(DjangoSpannerConfig): def ready(self): super().ready() # 还原被django_spanner修改的全局主键配置 settings.DEFAULT_AUTO_FIELD = "django.db.models.AutoField"INSTALLED_APPS里的"django_spanner"替换为"你的项目路径.FixedSpannerConfig"即可。 - 为Spanner侧模型显式指定适配主键
所有属于Spanner子应用的模型,不要使用全局默认的AutoField,显式导入Spanner专用的主键字段声明,适配Spanner的性能规则:
所有RDS侧的模型不需要额外修改,会自动使用全局默认的顺序自增主键,完全不受Spanner配置影响。from django.db import models from django_spanner.fields import SpannerAutoField class SpannerBizModel(models.Model): id = SpannerAutoField(primary_key=True) # 其余业务字段正常定义即可 - 拆分执行迁移操作
不要直接执行全量迁移,按数据库分开执行避免表结构错配:- RDS侧迁移:
python manage.py migrate --database=default - Spanner侧迁移:
python manage.py migrate 你的Spanner子应用名称 --database=spanner
- RDS侧迁移:
注意:如果之前已经执行过全量迁移,导致RDS侧表主键被替换为随机生成类型,需要先修正对应迁移文件里的主键字段定义为普通AutoField,再执行一次迁移还原表结构。
内容的提问来源于stack exchange,提问作者Sai Prakash
相关产品推荐
相关产品推荐

