Как запустить произвольный код после того, как Django " полностью загружен"

мне нужно выполнить некоторые довольно простые задачи после того, как моя среда Django была "полностью загружена".

более конкретно мне нужно делать вещи, как Signal.disconnect() некоторые сигналы Django, настроенные моей сторонней библиотекой по умолчанию и connect мои собственные сигналы, и мне нужно сделать некоторые "латание обезьяна" чтобы добавить функции удобства для некоторых моделей Django из другой библиотеки.

я делал это в моем приложении Django , который, кажется, хорошо работать для исправления обезьяны, но не работает для отключения моего сигнала. Проблема, по-видимому, заключается в синхронизации-по какой-то причине сторонняя библиотека всегда называет ее Signal.connect() после того, как я пытаюсь Signal.disconnect() его.

два вопроса:

есть ли у меня какие-либо гарантии, основанные на заказе моего INSTALLED_APPS порядок, когда мое приложение __init__.py модуль загружается?

есть ли подходящее место для логики, которая должна работать после приложения Django были полностью загружены в память?

4 ответов


в приложениях Django 1.7 можно реализовать метод ready (): https://docs.djangoproject.com/en/dev/ref/applications/#django.apps.AppConfig.ready


мой вопрос является более плохо сформулированным дубликатом этого вопроса:Куда Поместить Код Запуска Django. Ответ на этот вопрос:--3-->

напишите промежуточное ПО, которое делает это в init и затем поднять django.ядро.исключения.MiddlewareNotUsed от init, django удалит его для всех запросов...

смотрите Django документация по написанию собственного middleware.


мне пришлось сделать следующее исправление обезьяны. Я использую django 1.5 из филиала github. Я не знаю, правильно ли это, но это работает для меня.

Я не мог использовать промежуточное ПО, потому что я также хотел 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 включают import something прямо в функции. Этот импорт произойдет только в том случае, если вы фактически вызовете эту функцию. Единственный способ сделать то, что вы хотите, - это явно импортировать вещи, которые вы хотите исправить (которые вы должны иметь возможность делать где угодно), а затем исправить их. После этого любой другой импорт будет повторно использовать их.