让我们使用第三方应用程序创建一个django项目。我想在不接触原始文件的情况下覆盖它的一些模块。简单的子类化在这里是不可能的,需要透明地覆盖代码,因为许多其他应用程序依赖于原始类名和函数。
项目的结构看起来像:
django_project/
__init__.py
settings.py
overrides/ <-- here is a subdir with apps overrides
__init__.py
payment/ <-- here is an example of app to override
__init__.py
admin.py
forms.py <-- this file is ignored, original is imported
models.py
tests.py
views.py
用对settings.py
进行修饰
INSTALLED_APPS=(
'satchmo_store.shop'
#'payment' # original values
'overrides.payment' # modified app
...
)
然而,上述解决方案不起作用,因为Django不会将添加的应用程序的路径插入模块搜索路径(sys.path
)。Django只加载admin.py
、models.py
、tests.py
和views.py
,其他文件如forms.py
将被忽略。
这种行为有记录吗?在INSTALLED_APPS中放置模块名称的幕后作用是什么
我用manage.py
中的硬编码新模块搜索路径和Apache的WSGIPythonPath设置破解了这种情况。
import os.path
import sys
DIRNAME = os.path.dirname(__file__)
APPS_OVERRIDE = os.path.join(DIRNAME, 'overrides')
if not APPS_OVERRIDE in sys.path:
sys.path.insert(1, APPS_OVERRIDE)
我怀疑这是正确的方式。找不到描述应用程序覆盖的指南。
那么,如何在我的项目中正确地覆盖外部Django应用程序呢
额外的问题是:我需要复制整个应用程序目录树,而不仅仅是真正修改过的特定文件吗据我所知,Python会在第一个匹配的模块路径处停止,所以它不会导入搜索路径的以下部分中可用的其他模块。
如何覆盖表单的示例:
覆盖/支付/表单.py
from django import forms
class YourNewFormThingy(forms.Form): pass
覆盖/支付/型号.py
from satchmo.payment import forms as satchmo_payment_forms
from . import forms
satchmo_payment_forms.SomeForm = forms.YourNewFormThingy
尝试将payment
与override.payment
一起包含,因为satchmo
使用payment
模块来处理付款,而payment
代码也足够灵活,可以包含您的代码。