python django monkeypatching django-signals

python - Cómo ejecutar código arbitrario después de que Django esté “cargado completamente”



monkeypatching django-signals (4)

Necesito realizar algunas tareas bastante simples después de que mi entorno Django se haya "cargado completamente".

Más específicamente, necesito hacer cosas como Signal.disconnect() algunas señales de Django que están configuradas por mi biblioteca de terceros de forma predeterminada y connect mis propias señales y debo hacer algunos "parches de mono" para agregar funciones de conveniencia a algunos modelos de Django desde otra biblioteca

He estado haciendo esto en el archivo __init__.py mi aplicación Django, que parece funcionar bien para los parches de mono, pero no funciona para desconectar mi Señal. El problema parece ser uno de los tiempos, por la razón que sea que la Biblioteca de terceros siempre parece llamar a su Signal.connect() después de Signal.disconnect() intentado Signal.disconnect() .

Así que dos preguntas:

¿Tengo alguna garantía basada en el orden de mis INSTALLED_APPS el orden en que se carga el módulo __init__.py mi aplicación?

¿Hay un lugar adecuado para poner la lógica que debe ejecutarse después de que las aplicaciones de Django se hayan cargado completamente en la memoria?




Que yo sepa, no existe tal cosa como "completamente cargado". Un montón de funciones de Django incluyen import something directamente en la función. Esas importaciones solo sucederán si realmente invocas esa función. La única forma de hacer lo que usted quiere es importar explícitamente las cosas que desea parchear (que debería poder hacer en cualquier lugar) y luego parchearlas. A partir de entonces, cualquier otra importación los reutilizará.


Tuve que hacer el siguiente parche de mono. Yo uso django 1.5 de la rama github. No sé si esa es la forma correcta de hacerlo, pero funciona para mí.

No podía usar middleware, porque también quería que los scripts manage.py se vieran afectados.

De todos modos, aquí hay un parche bastante simple:

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

y luego podrías usar esta señal como cualquier otra:

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