我们在Django 1.9应用程序中使用了第三方库。我们想要使用一些不在原始应用程序中的功能(针对MongoDB)来修改该应用程序。我们目前通过我们自己的原始库的fork进行此操作,但是希望使更改更正交,以便最终可以将它们拉到上游。
我们在应用config ready()
期间尝试过修补,但是在django.apps.registry.populate()
中的此次调用之前处理了模型导入,并且在\__init__
中执行模型导入会遇到apps_ready == False
。执行此操作的生命周期中最好的部分是什么?
class MongoConfig(AppConfig):
def __init__(self, app_name, app_module):
super(MongoConfig, self).__init__(app_name, app_module)
for p in patches:
patch(*p)
def patch(old, new):
old_module, old_item = split_mod(old)
new_module, new_item = split_mod(new)
print('patching {0} with {1}'.format(old, new))
old_module = import_module(old_module)
new_module = import_module(new_module)
setattr(old_module, old_item, getattr(new_module, new_item))
答案 0 :(得分:1)
我真的不喜欢猴子补丁(除非在测试用例期间,即便如此我认为模拟更好)。
为什么不尝试更简单的选项?在您的项目中创建应用程序的代理(由于Python的查找系统,它将首先被调用)然后只需修补您想要的方法,并绕过您不在原始应用程序中的方法。
因此,如果组件被调用" FooProject"你会创建另一个名为" FooProject"在您的项目中,在此应用的__init__.py
:
from originalproject import FooProject as OriginalFoo
class FooProject(OriginalFoo):
def override_method_here(self, foo):
return my_own_magic(foo)
答案 1 :(得分:0)
猴子修补是一种破解,很难维护,应该避免。
原则是在加载Django之前,在导入之前修补代码。根据您的入口点,您将找到修补代码的正确位置。
使用Django 1.9我可以考虑两个切入点:
答案 2 :(得分:0)
我只是需要修补django-allauth/django-invitation
适配器,并偶然发现相同的限制(apps_ready == False
)。
所以我部分地使用了@domtes提到的内容,编辑manage.py
并插入一个方法来部分重写我必须修改的适配器,从而附加所需的行为。加载django
django-invitations
时,该方法已被重写。
这是一个简单,肮脏,可能不推荐的搜索&替换我重写了属于库结构的目标.py
文件的方法。
它假设与未来版本兼容,但我承认它是错误和问题的来源。
干杯
答案 3 :(得分:0)
我最终在初始化的wsgi部分完成了此操作
在wsgi.py
# Monkey Patch a few things
from huey_monitor.apps import HueyMonitorConfig
HueyMonitorConfig.verbose_name = 'Task Monitor'