【发布时间】: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 中,我有一个名为DBTask 的Task 子类,其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 django 和django.setup() 放入celery.py 或clearblackbox.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中删除这些上传功能并不是一个真正的选择。