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

Windows10下Django4.1对接Cloud SQL/Secrets Manager执行migrations报错排查

Django迁移报错“Models aren't loaded yet”排查与解决(Google Cloud SQL + Secrets Manager场景)

错误核心原因

这个错误本质是Django在完成模型加载流程前,就执行了依赖数据库连接或模型的操作,结合你的场景,大概率和Secrets Manager密钥获取逻辑、数据库配置初始化顺序有关。


排查步骤(按优先级)

1. 先排除数据库连接问题

既然cloud-sql-proxy已运行,直接手动验证连通性:

mysql -u <你的数据库用户名> -p --host 127.0.0.1 --port <proxy监听端口>

输入密码后能正常登录数据库 → 数据库和proxy无问题,排除数据库层面故障。

2. 排查Secrets Manager配置

  • 检查Secrets Manager中存储的数据库凭证(用户名、密码、库名)是否完全正确,无拼写/格式错误
  • 确认当前运行Django的服务账号拥有roles/secretmanager.secretAccessor权限,没有该权限会导致密钥获取失败,进而破坏数据库配置
  • 检查密钥版本是否为最新有效版本,避免引用已过期/禁用的版本

3. 重点检查settings.py代码问题

这是该错误的高发区,常见问题及修正:

错误写法示例(触发初始化顺序问题)

如果你的settings.py直接在模块顶层调用Secret Manager客户端获取密钥:

from google.cloud import secretmanager

# 错误:在Django初始化前执行密钥获取
client = secretmanager.SecretManagerServiceClient()
secret_response = client.access_secret_version(name="projects/xxx/secrets/db-password/versions/latest")
db_password = secret_response.payload.data.decode('UTF-8')

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mydb',
        'USER': 'db-user',
        'PASSWORD': db_password,
        'HOST': '127.0.0.1',
        'PORT': '3306',
    }
}

这种写法会在Django完成核心初始化前就执行网络请求和配置赋值,打乱加载顺序,触发模型加载异常。

修正方案

方案一:用AppConfig延迟加载密钥

在你的主app的apps.py中修改:

from django.apps import AppConfig
from google.cloud import secretmanager

class YourAppConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'your_app_name'

    def ready(self):
        # 此方法在Django初始化完成后执行
        from django.conf import settings
        client = secretmanager.SecretManagerServiceClient()
        response = client.access_secret_version(name="projects/xxx/secrets/db-password/versions/latest")
        db_password = response.payload.data.decode('UTF-8')
        settings.DATABASES['default']['PASSWORD'] = db_password

然后在settings.py的INSTALLED_APPS中替换原app名:

INSTALLED_APPS = [
    'your_app_name.apps.YourAppConfig',
    # 其他应用...
]
方案二:用环境变量传递密钥

在启动Django前,先通过脚本获取Secrets Manager密钥并设置为环境变量,比如:

# Windows命令行
for /f %i in ('gcloud secrets versions access latest --secret="db-password"') do set DB_PASSWORD=%i

然后settings.py中读取环境变量:

import os

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': os.environ.get('DB_NAME'),
        'USER': os.environ.get('DB_USER'),
        'PASSWORD': os.environ.get('DB_PASSWORD'),
        'HOST': '127.0.0.1',
        'PORT': '3306',
    }
}

利用报错堆栈精准定位

查看报错堆栈的最后几行:

  • 若堆栈指向Secret Manager客户端代码 → 密钥获取时机/权限问题
  • 若堆栈指向DATABASES配置代码 → 数据库配置不完整
  • 若堆栈指向模型导入语句 → 存在过早导入模型的代码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 19:13:28