【问题标题】:Upgrading Django from 1.8.6 to 1.9--django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet; importing models issue将 Django 从 1.8.6 升级到 1.9--django.core.exceptions.AppRegistryNotReady:应用尚未加载;导入模型问题
【发布时间】:2016-02-10 19:30:16
【问题描述】:

我正在尝试从 Django 1.8.6 升级到 1.9,但在尝试让项目正确构建和运行时遇到了麻烦。我已经更改了升级所需的许多东西,例如在my_app 中创建一个apps.py 文件并定义配置并在settings.py 中的INSTALLED_APPS 中包含它们的虚线路径(并将INSTALLED_APPS 更改为列表),但是我每次得到的相同错误是:

django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.

对于一些背景信息,该项目使用 Docker Compose。用于运行 Django 服务器的 web 容器本身的 Dockerfile 使用 paver 启动,以便在运行 docker-compose up 时执行以下命令:

./manage.py makemigrations --noinput
./manage.py migrate --noinput
./manage.py collectstatic --noinput
pip install --upgrade pip
pip install --upgrade -r requirements.txt
./manage.py runserver 0.0.0.0:8000

据我所知,没有任何依赖项与 Django 1.9 不兼容,所以我不确定这是否是这里的问题。我最初认为可能不兼容的唯一依赖项是django_hstore,但在 1.9 正式发布后不久就对其进行了更新以实现兼容性。因此,除非django_hstore 的创建者是错误的或说谎的(我对此表示怀疑),否则我真的想不出任何不兼容的依赖项。使用的数据库后端是django.db.backends.postgresql_psycopg2。还有一个worker 容器,它使用与web 相同的Dockerfile,用于运行Celery。来自 Django worker 容器的完整错误回溯如下:

worker_1 | Traceback (most recent call last):
worker_1 |   File "/usr/local/bin/celery", line 11, in <module>
worker_1 |     sys.exit(main())
worker_1 |   File "/usr/local/lib/python2.7/site-packages/celery/__main__.py", line 30, in main
worker_1 |     main()
worker_1 |   File "/usr/local/lib/python2.7/site-packages/celery/bin/celery.py", line 81, in main
worker_1 |     cmd.execute_from_commandline(argv)
worker_1 |   File "/usr/local/lib/python2.7/site-packages/celery/bin/celery.py", line 770, in execute_from_commandline
worker_1 |     super(CeleryCommand, self).execute_from_commandline(argv)))
worker_1 |   File "/usr/local/lib/python2.7/site-packages/celery/bin/base.py", line 309, in execute_from_commandline
worker_1 |     argv = self.setup_app_from_commandline(argv)
worker_1 |   File "/usr/local/lib/python2.7/site-packages/celery/bin/base.py", line 469, in setup_app_from_commandline
worker_1 |     self.app = self.find_app(app)
worker_1 |   File "/usr/local/lib/python2.7/site-packages/celery/bin/base.py", line 489, in find_app
worker_1 |     return find_app(app, symbol_by_name=self.symbol_by_name)
worker_1 |   File "/usr/local/lib/python2.7/site-packages/celery/app/utils.py", line 238, in find_app
worker_1 |     sym = imp(app)
worker_1 |   File "/usr/local/lib/python2.7/site-packages/celery/utils/imports.py", line 101, in import_from_cwd
worker_1 |     return imp(module, package=package)
worker_1 |   File "/usr/local/lib/python2.7/importlib/__init__.py", line 37, in import_module
worker_1 |     __import__(name)
worker_1 |   File "/code/my_app/tasks.py", line 3, in <module>
worker_1 |     from taskman.celery import app, DBTask
worker_1 |   File "/code/taskman/celery.py", line 6, in <module>
worker_1 |     from utils.db.clearblackbox import rm_invalid_blackbox
worker_1 |   File "/code/utils/db/clearblackbox.py", line 9, in <module>
worker_1 |     django.setup()
worker_1 |   File "/usr/local/lib/python2.7/site-packages/django/__init__.py", line 18, in setup
worker_1 |     apps.populate(settings.INSTALLED_APPS)
worker_1 |   File "/usr/local/lib/python2.7/site-packages/django/apps/registry.py", line 85, in populate
worker_1 |     app_config = AppConfig.create(entry)
worker_1 |   File "/usr/local/lib/python2.7/site-packages/django/apps/config.py", line 142, in create
worker_1 |     app_module = import_module(app_name)
worker_1 |   File "/usr/local/lib/python2.7/importlib/__init__.py", line 37, in import_module
worker_1 |     __import__(name)
worker_1 |   File "/code/utils/db/blackboxquery.py", line 2, in <module>
worker_1 |     from my_app.models import BlackBox, DataPoint, Value, SourceInfo, FormatString, Argument
worker_1 |   File "/code/my_app/models.py", line 11, in <module>
worker_1 |     class Value(models.Model):
worker_1 |   File "/usr/local/lib/python2.7/site-packages/django/db/models/base.py", line 94, in __new__
worker_1 |     app_config = apps.get_containing_app_config(module)
worker_1 |   File "/usr/local/lib/python2.7/site-packages/django/apps/registry.py", line 239, in get_containing_app_config
worker_1 |     self.check_apps_ready()
worker_1 |   File "/usr/local/lib/python2.7/site-packages/django/apps/registry.py", line 124, in check_apps_ready
worker_1 |     raise AppRegistryNotReady("Apps aren't loaded yet.")
worker_1 | django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.

我看到许多类似的问题在升级到 1.9 时出现相同的 AppRegistryNotReady 异常,但在我的情况下,我可以明确指出这是因为我的 AppConfig 位于 apps.py 中的应用程序之一在推荐时导入模型不要这样做。关于应用程序设置的 Django 1.9 文档说:

在这个阶段,您的代码不应导入任何模型!

换句话说,应用程序的根包和定义应用程序配置类的模块不应该导入任何模型,即使是间接的。

严格来说,Django 允许在加载应用程序配置后导入模型。但是,为了避免不必要地限制 INSTALLED_APPS 的顺序,强烈建议在此阶段不要导入任何模型。

不幸的是,文档似乎没有提供在设置阶段导入模型的替代方法,这很遗憾,因为我实际上无法避免导入模型。具体来说,在我的celery.py 中,我有一个名为DBTaskTask 子类,其on_error 回调使用模块函数来删除无效的数据库插入。该模块clearblackbox.py 导入模型,因为它需要对插入数据库的无效模型调用delete()DBTask 类用作名为insertBlackboxIntoDatabaseTask 的主数据库插入任务的基类。由于我无法在setup() 阶段导入模型,我还能做些什么来克服这个错误并能够再次运行我的服务器?

编辑: 我想知道我是否有任何不必要的配置,所以除了两个之外我都删除了:my_app.apps.TasksConfig,其name 字段指向我的@ 987654350@ 包含我的数据库插入任务的定义,taskman.celery.CeleryConfig 覆盖 ready 以便它自动检测来自 INSTALLED_APPS 的任务。虽然我将taskman.celery.CeleryConfig 放入INSTALLED_APPS,但我现在得到的错误是

ImportError: No module named CeleryConfig

如果我将import djangodjango.setup() 放入celery.pyclearblackbox.py 以尝试解决由于在设置期间导入模型而发生的AppRegistryNotReady 异常,则会发生这种情况。

【问题讨论】:

  • 我在 Django 1.8.x 系列中看到了一个与此类似的错误作为回归。这意味着 INSTALLED_APPS 中的一个应用程序不可用于导入。您可以尝试从 virtualenv 中的 Python shell 中的 INSTALLED_APPS 导入每个应用程序吗?这可能会找到罪魁祸首。
  • @FlipperPA 你可能会误解这里。我正在使用 Docker Compose,所以没有 virtualenv。我已经知道哪个应用程序不可导入——它是我的 CeleryConfig 的应用程序,因为它间接导入模型。我要问的不是哪个应用程序可能是罪魁祸首,而是如何解决我在问题中描述的导入问题。
  • @AviahLaor 在views.py 我有上传函数,最终调用用芹菜运行的数据库插入任务。在我的 docker-compose.yml 文件中,我有一个名为 worker 的 Celery 容器,它使用命令 bash -c "celery worker --app=my_app.tasks --autoreload -l DEBUG" 运行。
  • 似乎在 django 设置完成之前调用了 Celery。尝试从这些视图中移动这些功能。应用注册表只有在import django;django.setup() 准备好后才可用
  • 恐怕不可能。这些上传函数需要在views.py 中,因为它们是从使用 Django REST 框架的 APIViews 调用的。彻底重构代码以从views.py 中删除这些上传功能并不是一个真正的选择。

标签: python django celery


【解决方案1】:

最终对我有用的是删除 apps.py 中的所有配置,除了 TasksConfig,然后修改 clearblackbox.pycelery.py 中的导入。在clearblackbox.py 中,我将模型导入移动到函数本身而不是将其留在顶部,在celery.py 中,我将函数的导入从clearblackbox.py 移动到on_failureon_failure 定义DBTask,而不是将导入留在顶部。完成此操作后,将虚线路径放置到 TasksConfigCeleryConfig 最终工作。

【讨论】:

    猜你喜欢
    • 2016-03-06
    • 2016-08-04
    • 1970-01-01
    • 2016-03-11
    • 2015-11-12
    • 2016-03-10
    • 1970-01-01
    • 2014-10-21
    相关资源
    最近更新 更多