20

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

更具体地说,我需要做一些事情,比如Signal.disconnect()默认情况下由我的第三方库设置的一些 Django 信号和connect我自己的信号,我需要做一些“猴子补丁”来为来自另一个库的一些 Django 模型添加便利功能。

我一直在我的 Django 应用程序__init__.py文件中做这些事情,这似乎对猴子修补工作正常,但对我的信号断开连接不起作用。问题似乎是时间问题之一——无论出于何种原因,第三方图书馆似乎总是Signal.connect()在我尝试之后调用Signal.disconnect()它。

所以两个问题:

INSTALLED_APPS根据我的应用程序__init__.py模块加载顺序的顺序,我有什么保证吗?

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

4

4 回答 4

13

在 Django 1.7 应用程序可以实现 ready() 方法:https ://docs.djangoproject.com/en/dev/ref/applications/#django.apps.AppConfig.ready

于 2014-01-27T13:01:57.403 回答
7

我的问题是这个问题的措辞更糟糕的重复:Where To Put Django Startup Code。答案来自那个问题:

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

请参阅有关编写您自己的中间件的 Django文档。

于 2011-03-28T20:39:39.037 回答
5

我必须做以下猴子补丁。我使用来自 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)
于 2013-01-22T10:41:55.587 回答
3

As far as I know there's no such thing as "fully loaded". Plenty of Django functions include import something right in the function. Those imports will only happen if you actually invoke that function. The only way to do what you want would be to explicitly import the things you want to patch (which you should be able to do anywhere) and then patch them. Thereafter any other imports will re-use them.

于 2011-03-26T01:03:45.837 回答