Django“完全加载”后如何运行任意代码

时间:2011-03-26 00:58:39

标签: python django monkeypatching django-signals

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

更具体地说,我需要执行Signal.disconnect()某些Django信号,这些信号默认由我的第三方库设置,connect我自己的信号,我需要做一些"monkey patching"到从其他库中为一些Django模型添加便利函数。

我一直在我的Django应用程序的__init__.py文件中执行此操作,这似乎适用于猴子修补,但不适用于我的信号断开连接。问题似乎是时间问题 - 无论出于何种原因,第三方图书馆在我尝试Signal.connect()之后似乎总是将其称为Signal.disconnect()

所以有两个问题:

根据INSTALLED_APPS我的应用__init__.py模块加载时的顺序,我是否有任何保证?

在 Django应用程序已完全加载到内存后,是否有适当的位置放置需要运行 的逻辑?

4 个答案:

答案 0 :(得分:7)

在Django 1.7中,Apps可以实现ready()方法:https://docs.djangoproject.com/en/dev/ref/applications/#django.apps.AppConfig.ready

答案 1 :(得分:5)

我的问题是这个问题的措辞较差:Where To Put Django Startup Code。答案来自这个问题:

  

编写在 init 中执行此操作的中间件,然后从 init 中提升django.core.exceptions.MiddlewareNotUsed,django将删除所有请求...

参见Django documentation on writing your own middleware

答案 2 :(得分:4)

我必须做以下猴子补丁。我从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)

答案 3 :(得分:3)

据我所知,没有“满载”这样的东西。在函数中有很多Django函数包括import something。只有在实际调用该函数时才会发生这些导入。做你想做的事的唯一方法是明确地导入你想要修补的东西(你应该可以在任何地方做),然后修补它们。此后,任何其他进口将重复使用它们。