如果在Django中存在,则动态调用方法

时间:2011-02-27 08:06:46

标签: python django dynamic

我正在创建基于Django的网站(我知道它是纯Python,所以也许那些熟悉Python的人也可以回答)我需要动态调用一些方法。

例如,我在我的网站中使用views.py中的方法“do_search()”的应用程序(模块)很少。然后我有一个模块,例如“搜索”,我希望有一个动作,可以在其他应用程序中调用所有现有的“do_search()”。当然我不想将每个应用程序添加到导入,然后直接调用它。我需要一些更好的方法来动态地完成它。

我可以从设置中读取INSTALLED_APPS变量,并以某种方式运行所有已安装的应用程序并查找具体方法?一段代码将在这里帮助很多:)

提前致谢! Ignas

2 个答案:

答案 0 :(得分:3)

我不确定我是否真的理解这个问题,但如果我离开,请在评论中澄清我的答案。

# search.py
searchables = []

def search(search_string):
    return [s.do_search(search_string) for s in searchables]

def register_search_engine(searchable):
    if hasattr(searchable, 'do_search'):
        # you want to see if this is callable also
        searchables.append(searchable)
    else:
        # raise some error perhaps


# views.py
def do_search(search_string):
    # search somehow, and return result

# models.py

# you need to ensure this method runs before any attempt at searching can begin
# like in models.py if this app is within installed_apps. the reason being that
# this module may not have been imported before the call to search.
import search
from views import do_search
search.register_search_engine(do_search)

至于注册搜索引擎的位置,django的信号文档中有一些有用的文档,与此相关。

  

您可以将信号处理和注册码放在任何您喜欢的地方。但是,您需要确保早期导入模块,以便在需要发送任何信号之前注册信号处理。这使得你的应用程序的models.py成为一个放置信号处理程序注册的好地方。

因此,您的models.py文件应该是注册搜索引擎的好地方。

我刚才想到的替代答案:

settings.py中,您可以设置一个声明所有搜索功能的设置。像这样:

# settings.py
SEARCH_ENGINES = ('app1.views.do_search', 'app2.views.do_search')

# search.py
from django.conf import settings
from django.utils import importlib

def search(search_string):
    search_results = []
    for engine in settings.SEARCH_ENGINES
       i = engine.rfind('.')
       module, attr = engine[:i], engine[i+1:]
       mod = importlib.import_module(module)
       do_search = getattr(mod, attr)
       search_results.append(do_search(search_string))
    return search_results

这与注册MIDDLEWARE_CLASSES和TEMPLATE_CONTEXT_PROCESSORS有点类似。以上是所有未经测试的代码,但如果你环顾django源代码,你应该能够充实它并删除任何错误。

答案 1 :(得分:0)

如果您可以通过

导入其他应用程序
import other_app

然后应该可以执行

 method = getattr(other_app, 'do_' + method_name)
    result = method()

但是你的方法值得怀疑。