Django 1.7:惰性评估以避免 "App registry isn't ready yet" in models.py
Django 1.7: Lazy evaluation to avoid "App registry isn't ready yet" in models.py
我在模型的方法定义中有一个查询:
'content_type_id': ContentType.objects.get_for_model(model).pk,
https://github.com/seperman/django-tagging/blob/develop/tagging/models.py#L107
它会引发 "App registry is not ready yet"。
将这一行放在另一个独立的函数中也无济于事,因为它仍然会被调用。
Django 文档:
Executing database queries with the ORM at import time in models
modules will also trigger this exception. The ORM cannot function
properly until all models are available.
如何让它懒惰地评估这一行?
我考虑过通过管理命令将其结果手动缓存在一个文件中。然后读取缓存的结果但是应该有很多better/cleaner解决方案(?)
./manage.py shell
Traceback (most recent call last):
File "./manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 385, in execute_from_command_line
utility.execute()
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 354, in execute
django.setup()
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/__init__.py", line 21, in setup
apps.populate(settings.INSTALLED_APPS)
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/apps/registry.py", line 108, in populate
app_config.import_models(all_models)
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/apps/config.py", line 202, in import_models
self.models_module = import_module(models_module_name)
File "/usr/lib/python2.7/importlib/__init__.py", line 37, in import_module
__import__(name)
File "/var/www/something.com/something/current/apps/riding/models.py", line 32, in <module>
class RidingSection(CategoryBase):
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/mptt/models.py", line 244, in __new__
cls = meta.register(cls)
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/mptt/models.py", line 325, in register
obj = getattr(cls, attr)
File "/var/www/something.com/something/current/apps/tagging/fields.py", line 54, in __get__
return edit_string_for_tags(Tag.objects.usage_for_model(owner))
File "/var/www/something.com/something/current/apps/tagging/models.py", line 148, in usage_for_model
usage = self.usage_for_queryset(queryset, counts, min_count)
File "/var/www/something.com/something/current/apps/tagging/models.py", line 185, in usage_for_queryset
return self._get_usage(queryset.model, counts, min_count, extra_joins, extra_criteria, params)
File "/var/www/something.com/something/current/apps/tagging/models.py", line 107, in _get_usage
'content_type_id': ContentType.objects.get_for_model(model).pk,
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/contrib/contenttypes/models.py", line 50, in get_for_model
defaults={'name': smart_text(opts.verbose_name_raw)},
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/db/models/manager.py", line 92, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/db/models/query.py", line 422, in get_or_create
return self.get(**lookup), False
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/db/models/query.py", line 345, in get
clone = self.filter(*args, **kwargs)
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/db/models/query.py", line 691, in filter
return self._filter_or_exclude(False, *args, **kwargs)
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/db/models/query.py", line 709, in _filter_or_exclude
clone.query.add_q(Q(*args, **kwargs))
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1287, in add_q
clause, require_inner = self._add_q(where_part, self.used_aliases)
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1314, in _add_q
current_negated=current_negated, connector=connector)
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1138, in build_filter
lookups, parts, reffed_aggregate = self.solve_lookup_type(arg)
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1076, in solve_lookup_type
_, field, _, lookup_parts = self.names_to_path(lookup_splitted, self.get_meta())
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1339, in names_to_path
field, model, direct, m2m = opts.get_field_by_name(name)
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/db/models/options.py", line 416, in get_field_by_name
cache = self.init_name_map()
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/db/models/options.py", line 445, in init_name_map
for f, model in self.get_all_related_m2m_objects_with_model():
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/db/models/options.py", line 563, in get_all_related_m2m_objects_with_model
cache = self._fill_related_many_to_many_cache()
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/db/models/options.py", line 577, in _fill_related_many_to_many_cache
for klass in self.apps.get_models():
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/utils/lru_cache.py", line 101, in wrapper
result = user_function(*args, **kwds)
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/apps/registry.py", line 168, in get_models
self.check_models_ready()
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/apps/registry.py", line 131, in check_models_ready
raise AppRegistryNotReady("Models aren't loaded yet.")
django.core.exceptions.AppRegistryNotReady: 模型尚未加载。
您在应用程序注册之前调用 _get_usage
。无论您在哪里调用它,都需要将其更改为已配置应用程序的位置。基本上,如果您在导入时需要模型,您应该使用 ready().
例如,如果您有一个 signals.py
,您可以这样做:
# in apps.py
class SomeAppConfig(AppConfig):
def ready(self):
from . import signals
或者您的情况:
# in apps.py
class SomeAppConfig(AppConfig):
def ready(self):
mgr = TagManager()
mgr._get_usage(#some_args)
如文档所述:ready() ... is called as soon as the registry is fully populated
django 标记在这里有点不体贴。
TagField is a descriptor,这意味着如果您访问 YourModel.tags
,它会运行执行数据库查询的代码。
碰巧 django-mptt 在启动期间(在加载应用程序缓存之前)遍历了 MPTTModel 类 的所有属性,因此恰好触发了此异常。
我不知道你如何在维护 API 的同时在 django 标记中防止这种情况(YourModel.tags
必须从 某处获取标签 ).像这样的问题可能是 django-tagging 不再维护的原因。
但是,我是 django-mptt 的维护者并且我committed a workaround。如果您升级到 mptt 的主版本,您应该会发现它现在可以工作了。
我在模型的方法定义中有一个查询:
'content_type_id': ContentType.objects.get_for_model(model).pk,
https://github.com/seperman/django-tagging/blob/develop/tagging/models.py#L107
它会引发 "App registry is not ready yet"。
将这一行放在另一个独立的函数中也无济于事,因为它仍然会被调用。
Django 文档:
Executing database queries with the ORM at import time in models modules will also trigger this exception. The ORM cannot function properly until all models are available.
如何让它懒惰地评估这一行? 我考虑过通过管理命令将其结果手动缓存在一个文件中。然后读取缓存的结果但是应该有很多better/cleaner解决方案(?)
./manage.py shell
Traceback (most recent call last):
File "./manage.py", line 10, in <module>
execute_from_command_line(sys.argv)
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 385, in execute_from_command_line
utility.execute()
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 354, in execute
django.setup()
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/__init__.py", line 21, in setup
apps.populate(settings.INSTALLED_APPS)
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/apps/registry.py", line 108, in populate
app_config.import_models(all_models)
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/apps/config.py", line 202, in import_models
self.models_module = import_module(models_module_name)
File "/usr/lib/python2.7/importlib/__init__.py", line 37, in import_module
__import__(name)
File "/var/www/something.com/something/current/apps/riding/models.py", line 32, in <module>
class RidingSection(CategoryBase):
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/mptt/models.py", line 244, in __new__
cls = meta.register(cls)
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/mptt/models.py", line 325, in register
obj = getattr(cls, attr)
File "/var/www/something.com/something/current/apps/tagging/fields.py", line 54, in __get__
return edit_string_for_tags(Tag.objects.usage_for_model(owner))
File "/var/www/something.com/something/current/apps/tagging/models.py", line 148, in usage_for_model
usage = self.usage_for_queryset(queryset, counts, min_count)
File "/var/www/something.com/something/current/apps/tagging/models.py", line 185, in usage_for_queryset
return self._get_usage(queryset.model, counts, min_count, extra_joins, extra_criteria, params)
File "/var/www/something.com/something/current/apps/tagging/models.py", line 107, in _get_usage
'content_type_id': ContentType.objects.get_for_model(model).pk,
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/contrib/contenttypes/models.py", line 50, in get_for_model
defaults={'name': smart_text(opts.verbose_name_raw)},
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/db/models/manager.py", line 92, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/db/models/query.py", line 422, in get_or_create
return self.get(**lookup), False
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/db/models/query.py", line 345, in get
clone = self.filter(*args, **kwargs)
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/db/models/query.py", line 691, in filter
return self._filter_or_exclude(False, *args, **kwargs)
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/db/models/query.py", line 709, in _filter_or_exclude
clone.query.add_q(Q(*args, **kwargs))
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1287, in add_q
clause, require_inner = self._add_q(where_part, self.used_aliases)
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1314, in _add_q
current_negated=current_negated, connector=connector)
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1138, in build_filter
lookups, parts, reffed_aggregate = self.solve_lookup_type(arg)
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1076, in solve_lookup_type
_, field, _, lookup_parts = self.names_to_path(lookup_splitted, self.get_meta())
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1339, in names_to_path
field, model, direct, m2m = opts.get_field_by_name(name)
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/db/models/options.py", line 416, in get_field_by_name
cache = self.init_name_map()
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/db/models/options.py", line 445, in init_name_map
for f, model in self.get_all_related_m2m_objects_with_model():
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/db/models/options.py", line 563, in get_all_related_m2m_objects_with_model
cache = self._fill_related_many_to_many_cache()
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/db/models/options.py", line 577, in _fill_related_many_to_many_cache
for klass in self.apps.get_models():
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/utils/lru_cache.py", line 101, in wrapper
result = user_function(*args, **kwds)
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/apps/registry.py", line 168, in get_models
self.check_models_ready()
File "/var/www/something.com/something/shared/env/local/lib/python2.7/site-packages/django/apps/registry.py", line 131, in check_models_ready
raise AppRegistryNotReady("Models aren't loaded yet.")
django.core.exceptions.AppRegistryNotReady: 模型尚未加载。
您在应用程序注册之前调用 _get_usage
。无论您在哪里调用它,都需要将其更改为已配置应用程序的位置。基本上,如果您在导入时需要模型,您应该使用 ready().
例如,如果您有一个 signals.py
,您可以这样做:
# in apps.py
class SomeAppConfig(AppConfig):
def ready(self):
from . import signals
或者您的情况:
# in apps.py
class SomeAppConfig(AppConfig):
def ready(self):
mgr = TagManager()
mgr._get_usage(#some_args)
如文档所述:ready() ... is called as soon as the registry is fully populated
django 标记在这里有点不体贴。
TagField is a descriptor,这意味着如果您访问 YourModel.tags
,它会运行执行数据库查询的代码。
碰巧 django-mptt 在启动期间(在加载应用程序缓存之前)遍历了 MPTTModel 类 的所有属性,因此恰好触发了此异常。
我不知道你如何在维护 API 的同时在 django 标记中防止这种情况(YourModel.tags
必须从 某处获取标签 ).像这样的问题可能是 django-tagging 不再维护的原因。
但是,我是 django-mptt 的维护者并且我committed a workaround。如果您升级到 mptt 的主版本,您应该会发现它现在可以工作了。