我有一个 Django 项目。这个 Django 项目的一部分是一个报告模块,它在所有 INSTALLED_APPS 中搜索报告目录,非常类似于管理界面的自动发现机制。
这个模块有一个小的注册类,用于注册找到的类。以一种非常简化的方式,它看起来像这样:
def autodiscover():
"""
Searches for reports module in all INSTALLED_APPS
"""
global REPORTSLOADING
if REPORTSLOADING:
return
REPORTSLOADING = True
import imp
from django.conf import settings
for app in settings.INSTALLED_APPS:
try:
app_path = import_module(app).__path__
except AttributeError:
continue
try:
imp.find_module('reports', app_path)
except ImportError:
continue
import_module("%s.reports" % app)
REPORTSLOADING = False
class ReportsRegistery(object):
.....
registery = ReportsRegistery()
如果任何 INSTALLED_APPS 需要注册一个 Report 类,我们需要在里面写一行reports/__init__.py
:
import reports
reports.registery.register(SomeReportClass)
在主要的 urls.py 中,我会这样做:
import reports
reports.autodiscover()
urlpatterns = patterns('',
....
(r'', include(reports.registery.urls)),
)
现在我决定为它创建一个可插入的 django 应用程序,并将相同的代码放入__init__.py
包中。我面临的问题是具有新结构的报告模块被导入两次,从而导致重新创建“注册”对象。因此,实际上没有注册任何网址。它从 urls.py 中的导入加载一次(如预期的那样),另一次由自动发现启动。我已经通过以下方式验证了这一点:
print hex(id(registery))
并发现它返回了 2 个不同的值。
我认为报告包将被导入一次,就像它只是一个模块一样。
如何防止它被加载两次?或者我如何确保我们只有一个 ReportsRegistery 实例可以使用?