Python Django之后如何运行任意代码;满载;

Python Django之后如何运行任意代码;满载;,python,django,monkeypatching,django-signals,Python,Django,Monkeypatching,Django Signals,在Django环境“完全加载”之后,我需要执行一些相当简单的任务 更具体地说,我需要做一些事情,比如Signal.disconnect()一些由我的第三方库默认设置的Django信号和connect我自己的信号,我需要做一些事情,从另一个库向一些Django模型添加方便的函数 我一直在Django应用程序的\uuuu init\uuuuu.py文件中做这件事,它似乎对猴子补丁很有效,但对我的信号断开不起作用。问题似乎是时间问题——无论出于何种原因,在我尝试Signal.disconnect()之

在Django环境“完全加载”之后,我需要执行一些相当简单的任务

更具体地说,我需要做一些事情,比如
Signal.disconnect()
一些由我的第三方库默认设置的Django信号和
connect
我自己的信号,我需要做一些事情,从另一个库向一些Django模型添加方便的函数

我一直在Django应用程序的
\uuuu init\uuuuu.py
文件中做这件事,它似乎对猴子补丁很有效,但对我的信号断开不起作用。问题似乎是时间问题——无论出于何种原因,在我尝试
Signal.disconnect()
之后,第三方库似乎总是调用它的
Signal.connect()

所以有两个问题:

根据我的
已安装的应用程序的顺序
以及我的应用程序的
\uuuuuu init\uuuuuuuuuy.py
模块的加载顺序,我是否有任何保证


在Django应用程序被完全加载到内存后,是否有合适的位置来放置需要运行的逻辑。很多Django函数都包括
导入函数中右边的内容。这些导入只有在您实际调用该函数时才会发生。做你想做的事情的唯一方法是显式地导入你想修补的东西(你应该可以在任何地方做),然后修补它们。此后,任何其他导入都将重复使用它们。

我的问题是这个问题的一个措辞更糟糕的重复:。答案来自这个问题:

编写在init中执行此操作的中间件,然后在init中引发django.core.exceptions.MiddleWareNotus,django将在所有请求中删除它


见Django。

我不得不做以下猴子修补。我使用github分支的django 1.5。我不知道这样做是否合适,但对我来说很有效

我无法使用中间件,因为我还希望manage.py脚本受到影响

无论如何,这里有一个相当简单的补丁:

import django
from django.db.models.loading import AppCache

django_apps_loaded = django.dispatch.Signal()

def populate_with_signal(cls):
    ret = cls._populate_orig()
    if cls.app_cache_ready():
        if not hasattr(cls, '__signal_sent'):
            cls.__signal_sent = True
            django_apps_loaded.send(sender=None)
    return ret

if not hasattr(AppCache, '_populate_orig'):
    AppCache._populate_orig = AppCache._populate
    AppCache._populate = populate_with_signal
然后你可以像其他信号一样使用这个信号:

def django_apps_loaded_receiver(sender, *args, **kwargs):
    # put your code here.
django_apps_loaded.connect(django_apps_loaded_receiver)

在Django 1.7中,应用程序可以实现ready()方法:

它的可能副本是此方法的副本:或者相反。有趣。我喜欢这适用于
管理
命令,但是这里访问了太多“受保护”的属性,我担心它会在Django版本之间中断。实际上,唯一特定于Django的受保护属性是“AppCache.\u populate”。其余的都是我自己的发明;)到目前为止(django1.5),似乎还没有更干净的方法来实现这一点。相信我,我希望它是干净的。我在github找到了django ticket:我也在github找到了这个文件:但是因为它是一个fork,我不会冒险使用它,除非它是django的官方部分。把这个monkeypatch放在哪里最好呢。。。实际上,我有一个单独的django应用程序,叫做signals,它是INSTALLED_APPS列表中的最后一个。上面的补丁位于signals::models.py文件中。当您使用url.py时,manage.py脚本不会受到影响(这对我来说不是一个理想的解决方案),这是一个好东西-谢谢。我发现“用信号填充”中的“cls.app\u cache\u ready()”总是返回False,因此信号从未发送。我试图通过移除“cls.app_cache_ready()”并在我将信号接收器连接到django_apps_load后调用“django.db.models.get_models()”来解决这个问题,希望get_models强制应用缓存填充。到目前为止,这似乎是可行的(我使用的是django 1.5.1),我发现它在第一次请求时就完成了所有事情,这很可怕。。。它应该在启动时完成。同意。在第一次请求时执行此操作会破坏预加载或准备任何内容的目的。使用此操作在现有数据上运行数据库查询与SQL内存测试不兼容:(这仅在您能够修改
设置时有效。已安装的应用程序
。导致此问题的许多用例都没有这种奢侈。