You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django数据库路由迁移报错:django_migrations表id列多默认值问题

问题描述

尝试配置DATABASE ROUTER,将myapp应用的RedshiftModel路由至Redshift数据库,其余模型路由至PostgreSQL。执行命令python manage.py migrate --database redshift时,出现以下错误:

SyntaxError: multiple default values specified for column "id" of table "django_migrations"
ProgrammingError: multiple default values specified for column "id" of table "django_migrations"
MigrationSchemaMissing: Unable to create the django_migrations table (multiple default values specified for column "id" of table "django_migrations")

Redshift中尚未存在django_migrations表,怀疑路由的allow_migrate方法逻辑有误。相关代码如下:

路由代码(routers.py)

class DbRouter:
    
    def db_for_read(self, model, **hints):
        if model._meta.app_label == 'myapp':
            if model._meta.model_name == 'RedshiftModel':
                return 'redshift'
            else:
                return 'default'
        return None
    
    def db_for_write(self, model, **hints):
        if model._meta.app_label == 'myapp':
            if model._meta.model_name == 'RedshiftModel':
                return 'redshift'
            else:
                return 'default'
        return None
    
    def allow_relation(self, obj1, obj2, **hints):
        if obj1._meta.app_label == 'myapp' or obj2.app_label == 'myapp':
            return True
        return None
        
    def allow_migrate(self, db, app_label, model_name=None, **hints):
        if app_label == 'myapp':
            if model_name == 'RedshiftModel':
                return db == 'redshift'
            else:
                return db == 'default'
        return None

模型代码(models.py)

class RedshiftModel(models.Model):
    date = models.DateField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = '"int". "redshift_table"'
        app_label = 'myapp'

数据库配置(settings.py)

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': os.environ.get('NAME'),
        'USER': os.environ.get('USER'),
        'PASSWORD': os.environ.get('PASSWORD'),
        'HOST': os.environ.get('HOST'),
        'PORT': os.environ.get('PORT'),
    },
    'redshift': {
        'ENGINE': 'django_redshift_backend',
        'NAME': os.environ.get('RDATABASE'),
        'USER': os.environ.get('RUSER'),
        'PASSWORD': os.environ.get('RPASSWORD'),
        'HOST': os.environ.get('RHOST'),
        'PORT': os.environ.get('RPORT'),
        'OPTIONS': {
            'options': '-c search_path=int'
        }
    }
}

DATABASE_ROUTERS = [
    'myproject.settings.routers.DbRouter'
]

解决方案

1. 核心问题分析

错误根源是django_redshift_backend在创建django_migrations系统表时,对id列生成了重复的默认值定义,导致Redshift无法创建该表。另外,你的RedshiftModel设置了managed = False,意味着Django不会为它生成迁移文件,也不需要对Redshift执行migrate操作——因为该模型对应的表已经在Redshift中存在。

2. 修复路由的allow_migrate方法

当前路由未处理Django系统表的迁移逻辑,导致执行migrate --database redshift时,Django尝试在Redshift创建系统表。修改allow_migrate方法,明确禁止在Redshift上执行任何迁移:

def allow_migrate(self, db, app_label, model_name=None, **hints):
    # 禁止所有迁移操作在redshift数据库执行
    if db == 'redshift':
        return False
    # myapp的非RedshiftModel迁移到default库
    if app_label == 'myapp':
        return db == 'default'
    # 其他app的迁移按默认逻辑处理
    return None

3. 正确操作流程

  • 对PostgreSQL(default库)执行正常迁移:python manage.py migrate
  • RedshiftModel是managed=False,无需生成迁移文件,直接在代码中使用即可,不要对Redshift执行migrate命令。

额外优化点

  • 模型中的db_table可简化写法,去掉转义字符,直接使用:
db_table = '"int"."redshift_table"'
  • 路由的读写方法可简化逻辑,无需嵌套判断:
def db_for_read(self, model, **hints):
    if model._meta.app_label == 'myapp' and model._meta.model_name == 'RedshiftModel':
        return 'redshift'
    return 'default'

def db_for_write(self, model, **hints):
    return self.db_for_read(model, **hints)

内容的提问来源于stack exchange,提问作者facepet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 23:06:34