bigywater.tech
Django · 13

App Registry:INSTALLED_APPS 如何加载应用

INSTALLED_APPS 是怎么变成 apps 注册表的?为什么在 apps.py 或 settings 里 import 模型会炸?这篇把注册表的三个阶段、各种配置错误的报错原文,以及 AppConfig 自动发现的一个安静的坑,都用真实项目跑一遍。

3 个标志
apps_ready → models_ready → ready:models 导入时只有 apps_ready,ready() 里 models_ready 为 True
AppRegistryNotReady
setup() 之前 get_model 或 import 模型都会报这个错
安静的坑
apps.py 里有多个 AppConfig 子类且都没标 default = True 时,退回基类 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() 之前使用注册表

实测 · 本机执行输出
  [未 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」。

AppConfig 的自动发现

实测 · 本机执行输出
  [两个子类,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' 可以避免歧义。

分步演示:注册表的状态

App Registry
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 / Python 3.14.7 / Django 6.1.1(默认用 SQLite,其它数据库会在文中注明),用 django.test.Client 或真实的本机服务器进程实测;计时用 time.perf_counter,数字每次运行会有小幅抖动
    • 没有验证:apps.py 存在但没有任何 AppConfig 子类时的行为、多 app 共享同一模块的情形、apps.populate 的线程安全(文档说明但本文未测)、swappable 模型(AUTH_USER_MODEL)在注册表里的延迟解析
    京ICP备2026067502号-1京公网安备11010502063487号