Django多SQL Server遗留库执行migrate建表仅首个库生效问题求助
问题根因
Django 的数据库路由是按DATABASE_ROUTERS配置的顺序依次执行的,只要某一个路由返回了非None的布尔值,就会直接采用该结果,不会继续匹配后续的路由。
你的三个路由都把contenttypes、shared_invoice_detail加入了自己的route_app_labels,且原allow_migrate逻辑是:
- 只要app标签匹配,就直接返回
当前操作的db是否等于自己负责的db - 执行
migrate --database=comp2_db时,第一个匹配的是comp1Router,此时app标签符合,但db不等于comp1_db,所以直接返回False,Django就判定该app不需要在comp2_db迁移,comp2Router根本没有机会被调用。 - 同理
comp3_db的迁移也被第一个路由拦截了。
解决方案
1. 调整所有路由的allow_migrate逻辑
把判断逻辑反过来:先判断当前操作的DB是不是自己负责的,再判断是否允许对应app迁移,不属于自己负责的DB直接返回None交给后续路由处理。
修改后三个路由的allow_migrate参考如下(仅需修改对应DB名称即可):
# comp1Router的allow_migrate def allow_migrate(self, db, app_label, model_name=None, **hints): # 只处理属于自己负责的comp1_db的迁移判断 if db == 'comp1_db': return app_label in self.route_app_labels # 不是自己负责的DB不做判断,交给后续路由 return None # comp2Router的allow_migrate def allow_migrate(self, db, app_label, model_name=None, **hints): if db == 'comp2_db': return app_label in self.route_app_labels return None # comp3Router的allow_migrate def allow_migrate(self, db, app_label, model_name=None, **hints): if db == 'comp3_db': return app_label in self.route_app_labels return None
2. 清理历史迁移记录
因为之前执行迁移时,Django已经在comp2_db、comp3_db的django_migrations表中标记shared_invoice_detail的迁移已完成,需要先清理这部分错误记录:
# 回滚comp2_db的shared_invoice_detail迁移 python manage.py migrate shared_invoice_detail zero --database=comp2_db # 回滚comp3_db的shared_invoice_detail迁移 python manage.py migrate shared_invoice_detail zero --database=comp3_db
3. 重新执行迁移
python manage.py migrate --database=comp1_db python manage.py migrate --database=comp2_db python manage.py migrate --database=comp3_db
可选优化
如果不需要把auth、sessions等系统app的表同步到三个业务库,执行迁移时可以指定仅同步目标app,避免生成多余的表:
python manage.py migrate shared_invoice_detail --database=comp1_db
内容的提问来源于stack exchange,提问作者ChrisYen150
相关产品推荐
相关产品推荐

