0
我正在为我的Django项目编写小型应用程序。这个想法是创建一些小部件 - 小视图功能,可以通过包含标签添加到模板中以显示一些旁路信息(例如博客记录,快速链接列表,菜单等)。我想创建一个类似于默认templatetag
注册机制的东西。一般来说,我需要具备以下组件:python共享全局模块变量问题
- 定制的装饰注册在启动这些视图功能
- 一些功能将在所有已安装的应用程序特定模块搜索(“widgets.py”现在)(可能称为settings.py)
我写的现在看起来是这样的:
# -*- coding: utf-8 -*-
REGISTERED_WIDGETS = []
class Library(object):
"""
Utility class for registering defined widgets
"""
def widget(self, view=None, name=None, form_class=None):
if name is None:
name = view.__name__
def decorator(view):
print 'registering', view
REGISTERED_WIDGETS.append((view, name, form_class))
def wrapper(request, *args, **kwargs):
return view(request, *args, **kwargs)
return wrapper
if view is not None:
return decorator(view)
else:
return decorator
def search_widgets():
"""
Search for 'widgets.py' modules inside installed applications and import them,
hence initializing its registration
"""
from django.conf import settings
for app in settings.INSTALLED_APPS:
try:
module = __import__(app + '.widgets')
print module
except ImportError:
pass
else:
print 'Imported widgets from ', app
if __name__ == '__main__':
search_widgets()
print REGISTERED_WIDGETS
为了测试它,我加入widgets.py存根控件中的一个我应用:
# -*- coding: utf-8 -*-
from experiments.widgets.base import Library
register = Library()
@register.widget(name='dummy')
def dummy_widget(request):
pass
我卡住了一个愚蠢的问题 - 运行这个模块,我想看到充满发现的部件REGISTERED_WIDGETS变量时,但它是空的。其实我看到这个输出:
>>> %run widgets/base.py
<module 'django' from '/usr/lib/python2.7/dist-packages/django/__init__.pyc'>
Imported widgets from django.contrib.admin
registering <function dummy_widget at 0x364f320>
<module 'experiments' from '/home/east825/Development/pycharm-experiments/experiments/../experiments/__init__.pyc'>
Imported widgets from experiments.layout
[]
似乎我忘了一些非常重要的关于python共享全局变量的行为。 有何建议?
是的,你说得对 - 我接着说:打印ID(REGISTERED_WIDGETS)',看到这个列表中创建两次:第一次在主脚本,第二 - 通过__import__调用首次导入。这很奇怪,我总是假设一旦模块被加载到sys.modules中,它不会再被导入。但我仍然不知道如何解决这个问题,实际上它不应该是原因 - 第二个导入列表不会再次创建,并且此时添加的元组应该留在它中,不是吗?我也尝试做这个列表库类'字段,但它并没有帮助。有任何想法吗? – east825
如果您看到两次打印,则意味着定义了两个不同的REGISTERED_WIDGETS。第一个是你打印的,第二个是非空的。 检查python文档:http://docs.python.org/library/functions.html#__import__似乎问题出在你的__import__上,你应该像例子一样添加全局变量和局部变量。 我认为原因是导入两次,因为它看不到模块已经导入(因为你没有指定全局变量)。试试吧,让我知道:) – AlbertFerras
不,它没有帮助。在使用导入和共享全局变量玩了一段时间之后,我想到了一个想法 - 我看不到在模块内部发生的这些变化,这些变量被定义,因此它定义了它们自己的私有副本,然后将其作为__main__脚本运行。我重写了我的应用程序以将注册的窗口小部件存储为'Library'对象的字段,然后在'search_widgets'中将此字段值附加到'REGISTERED_WIDGETS'(实际上几乎与Django本身一样)。这按预期工作。感谢您将我推向正确的解决方案。 – east825