设置Django“插件”应用程序的别名

时间:2009-12-19 21:24:10

标签: python django

是否有一些pythonic方式通过别名加载django应用程序?我认为这是使应用程序更“可插拔友好”的一种方法。

在settings.py中使用了一种模式:

INSTALLED_APPS = ('... ','...', )

其中INSTALLED_APPS是包含应用名称的元组。 这很好,但我不想以这种方式明确地放入某些应用程序。

我希望将应用处理命名为external_login_app映射到drupal_loginmediawiki_login(由最终用户或第三方提供) ),其中实际自定义模块/应用程序的名称由settings.py

中的字符串变量提供

可插入部分(例如mediawiki_login)必须是具有自己的视图,模型,表单等的完整应用程序,而external_login_app必须可以在其余代码中的任何位置访问。< / p>

这里的目标是将分布式代码与插件解耦。

编辑1:以下是我正在尝试的内容:

在settings.py

EXTERNAL_LOGIN = __import__(EXTERNAL_LOGIN_APP) 
#setting name must be upper case according to
#django docs

但我的自定义登录应用程序也取决于设置文件,因此看起来我有一个循环导入问题,错误如module external_login does not have attribute views。 这个问题似乎非常隐蔽,因为我无法在settings.py中使用render_to_response语句导入的视图中使用__import__快捷方式等简单的内容。

尝试一段时间后

编辑2 我发现在settings.py调用中使用__import__()将无法正常工作,因为几乎不可避免的循环依赖

到目前为止,我发现的最佳工作方法是将__import__()调用放入应用程序的其他.py文件中,提供通用的“消费者”界面 - 调用插件函数的界面:

settings.py中的

Michał在他的回答中建议

EXTERNAL_LOGIN_APP = 'drupal_login'
INSTALLED_APPS = (
                  '...',
                  EXTERNAL_LOGIN_APP,
                )

e.g。在app/views.py

from django.conf import settings
EXTERNAL_LOGIN = __import__(settings.EXTERNAL_LOGIN_APP, \
                            [], [], ['api','forms'])

def login_view(request, external=False):
    if external:
        form = EXTERNAL_LOGIN.forms.LoginForm(request.POST)
        if form.is_valid():
            login = form.cleaned_data['login']
            password = form.cleand_data['password']
            if EXTERNAL_LOGIN.api.check_password(login, password):
                #maybe create local account, 
                #do local authentication
                #set session cookies for the 
                #external site to synchronize logins, etc.

2 个答案:

答案 0 :(得分:4)

LOGIN_APP_NAME = 'drupal_login' # or 'mediawiki_login', or whatever

在settings.py中尽早,然后在LOGIN_APP_NAME中添加INSTALLED_APPS(不带任何引号!),而不是实际应用的名称。

如果您需要更复杂的功能来确定要使用的应用程序,那么如何在INSTALLED_APPS中放置external_login_app()(函数调用 - 在它周围没有引号!)之类的东西,并让external_login_app函数返回任何它是应该根据settings.py中的设置返回,还是某个配置文件的内容或其他什么? (编辑: Tobu的回答显示了这样一个函数可能需要返回的内容以及如何使用__import__实现这一功能。)

无论如何,我不确定在解除部分网站方面是如何实现的 - 如果用户仍然需要修改settings.py,为什么不让他/她放入名称适当的应用程序在正确的地方? (编辑:好的,现在我有点看到在这里使用正确的解决方案可以获得什么......我想继续讨论如何最好地完成所需的工作。)

编辑:我在原始海报之前发布了这个,修改了任何编辑的问题,现在编辑2包括将登录应用的名称移动到settings.py中的单独变量的想法并在INSTALLED_APPS中包含变量。既然原始问题的两个编辑已经到位,我想我可以更清楚地看到问题,尽管这只是让我认为情况所要求的是abstract_login应用程序,后端支持{ {1}}模块处理drupal,mediawiki等登录方案。好吧,我不能说我现在可以提供那种东西......希望别人可以。如果再次编辑,我相信我有一个明智的想法,可以简化整个OP的编辑范围。

答案 1 :(得分:2)

在设置中定义应用名称(如Michał和您的编辑一样)效果很好:

EXTERNAL_LOGIN_APP = 'drupal_login'
INSTALLED_APPS = (
                  '...',
                  EXTERNAL_LOGIN_APP,
                )

同样在设置或公共模块中,您可以考虑导入应用程序:

def external_login_app():
    return __import__(EXTERNAL_LOGIN_APP, …)

在导入后使用它:

external_login_app = settings.external_login_app()