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?
En Django 1.7, las aplicaciones pueden implementar el método ready (): https://docs.djangoproject.com/en/dev/ref/applications/#django.apps.AppConfig.ready
Mi pregunta es un duplicado más mal redactado de esta pregunta: Dónde poner el código de inicio de Django . La respuesta viene de esa pregunta:
Escriba middleware que haga esto en init y luego levante django.core.exceptions.MiddlewareNotUsed del init , django lo eliminará para todas las solicitudes ...
Consulte la documentación de Django sobre cómo escribir su propio middleware .
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)