INSTALLED_APPS 是怎么变成 apps 注册表的?为什么在 apps.py 或 settings 里 import 模型会炸?这篇把注册表的三个阶段、各种配置错误的报错原文,以及 AppConfig 自动发现的一个安静的坑,都用真实项目跑一遍。
[导入模型与 ready() 时各标志的值]
(lab/models.py 导入时) apps_ready=True models_ready=False ready=False
(LabConfig.ready() 里) apps_ready=True models_ready=True ready=False
(setup() 结束后) apps_ready=True models_ready=True ready=True
app_configs 顺序: ['contenttypes', 'auth', 'lab', 'other']
get_models() 共 6 个,前几个: ['ContentType', 'Permission', 'Group', 'User', 'Item', 'Thing']
Item 的 app_label: lab在 lab/models.py 与 ready() 里各打印一次三个标志。注册表按 INSTALLED_APPS 的顺序排列 app,get_models() 也按这个顺序返回。模型的 app_label 由它所在的 app 决定。
[未 setup 就 get_model]
AppRegistryNotReady: Models aren't loaded yet.
[未 setup 就导入模型]
django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.在 settings.py、apps.py 顶层、或脚本里没 django.setup() 就 import 模型,都会得到 AppRegistryNotReady。解决办法:把导入挪到函数里、或 ready() 里。
[同一个 app 写两次] django.core.exceptions.ImproperlyConfigured: Application labels aren't unique, duplicates: lab ['lab' 与 'lab.apps.LabConfig' 同时写] django.core.exceptions.ImproperlyConfigured: Application labels aren't unique, duplicates: lab [两个 app 的 label 相同] django.core.exceptions.ImproperlyConfigured: Application labels aren't unique, duplicates: lab [INSTALLED_APPS 里写了不存在的 app] ModuleNotFoundError: No module named 'nonexistent_app' [模型所在的包不在 INSTALLED_APPS] RuntimeError: Model class stray.models.Stray doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.
label 重复时 Django 会拒绝启动;写了不存在的 app 得到普通的 ModuleNotFoundError;模型所在的包没进 INSTALLED_APPS 时,导入这个模型会得到「doesn't declare an explicit app_label」。
[两个子类,B 标了 default = True]
BConfig B(default = True)
[两个子类都没标 default] AppConfig
[没有 apps.py] AppConfig只写 'lab' 时,Django 去 lab/apps.py 找 AppConfig 子类:只有一个就用它;有多个时看谁标了 default = True;多个都没标时,这次实测退回基类 AppConfig 且不报错——你在子类里写的 ready()、verbose_name 就悄悄失效了。写成 'lab.apps.LabConfig' 可以避免歧义。