猴子在另一个应用程序中修补Django应用程序

时间:2016-05-06 13:46:27

标签: python django django-models django-apps

我们在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))

4 个答案:

答案 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我可以考虑两个切入点:

  1. wsgi.py - 您的代码在WSGI容器上运行
  2. manage.py - 运行任何管理命令(shell,runserver,migrate)时

答案 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'