2012-06-06 54 views
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共享全局变量的行为。 有何建议?

回答

1

你的模块base.py被导入两次可能是可能的吗?

在base.py的开始处添加一个打印,其中带有“print”base.py执行'“或其他东西。

编辑:或者更好的打印ID(REGISTERED_WIDGETS)

+0

是的,你说得对 - 我接着说:打印ID(REGISTERED_WIDGETS)',看到这个列表中创建两次:第一次在主脚本,第二 - 通过__import__调用首次导入。这很奇怪,我总是假设一旦模块被加载到sys.modules中,它不会再被导入。但我仍然不知道如何解决这个问题,实际上它不应该是原因 - 第二个导入列表不会再次创建,并且此时添加的元组应该留在它中,不是吗?我也尝试做这个列表库类'字段,但它并没有帮助。有任何想法吗? – east825

+0

如果您看到两次打印,则意味着定义了两个不同的REGISTERED_WIDGETS。第一个是你打印的,第二个是非空的。 检查python文档:http://docs.python.org/library/functions.html#__import__似乎问题出在你的__import__上,你应该像例子一样添加全局变量和局部变量。 我认为原因是导入两次,因为它看不到模块已经导入(因为你没有指定全局变量)。试试吧,让我知道:) – AlbertFerras

+0

不,它没有帮助。在使用导入和共享全局变量玩了一段时间之后,我想到了一个想法 - 我看不到在模块内部发生的这些变化,这些变量被定义,因此它定义了它们自己的私有副本,然后将其作为__main__脚本运行。我重写了我的应用程序以将注册的窗口小部件存储为'Library'对象的字段,然后在'search_widgets'中将此字段值附加到'REGISTERED_WIDGETS'(实际上几乎与Django本身一样)。这按预期工作。感谢您将我推向正确的解决方案。 – east825