Estoy escribiendo una clase de Django Middleware que quiero ejecutar solo una vez al inicio, para inicializar algún otro código arbitrario. He seguido la muy buena solución publicada por sdolan aquí , pero el mensaje "Hola" se envía al terminal dos veces . P.ej
from django.core.exceptions import MiddlewareNotUsed
from django.conf import settings
class StartupMiddleware(object):
def __init__(self):
print "Hello world"
raise MiddlewareNotUsed('Startup complete')
y en mi archivo de configuración de Django, tengo la clase incluida en el MIDDLEWARE_CLASSES
lista.
Pero cuando ejecuto Django usando runserver y solicito una página, entro en la terminal
Django version 1.3, using settings 'config.server'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
Hello world
[22/Jul/2011 15:54:36] "GET / HTTP/1.1" 200 698
Hello world
[22/Jul/2011 15:54:36] "GET /static/css/base.css HTTP/1.1" 200 0
¿Alguna idea de por qué "Hola mundo" se imprime dos veces? Gracias.
Respuestas:
Actualización de la respuesta de Pykler a continuación: Django 1.7 ahora tiene un gancho para esto
No lo hagas de esta manera.
No desea "middleware" para una cosa de inicio única.
Desea ejecutar código en el nivel superior
urls.py
. Ese módulo se importa y ejecuta una vez.urls.py
fuente
Actualización: Django 1.7 ahora tiene un gancho para esto
expediente:
myapp/apps.py
expediente:
myapp/__init__.py
Para Django <1.7
La respuesta número uno ya no parece funcionar, urls.py se carga a la primera solicitud.
Lo que ha funcionado últimamente es poner el código de inicio en cualquiera de sus INSTALLED_APPS init .py ej.
myapp/__init__.py
Cuando se usa
./manage.py runserver
... esto se ejecuta dos veces, pero eso se debe a que runserver tiene algunos trucos para validar primero los modelos, etc. ... implementaciones normales o incluso cuando las recargas automáticas de runserver, esto solo se ejecuta una vez.fuente
Esta pregunta está bien respondida en la publicación del blog Enlace de punto de entrada para proyectos de Django , que funcionará para Django> = 1.4.
Básicamente, puede
<project>/wsgi.py
hacerlo, y se ejecutará solo una vez, cuando se inicie el servidor, pero no cuando ejecute comandos o importe un módulo en particular.fuente
Si ayuda a alguien, además de la respuesta de pykler, la opción "--noreload" evita que el servidor de ejecución ejecute el comando al inicio dos veces:
Pero ese comando no volverá a cargar runserver después de los cambios de otros códigos también.
fuente
os.environ.get('RUN_MAIN')
solo ejecutar su código una vez en el proceso principal (consulte stackoverflow.com/a/28504072 )ready(self)
llamadas y al mismo tiempo pudo iniciarlas solo una vez. ¡Salud!runserver
Por defecto, Django inicia dos procesos con números pid distintos (diferentes).--noreload
hace que comience un proceso.Según lo sugerido por @Pykler, en Django 1.7+ debe usar el gancho explicado en su respuesta, pero si desea que se llame a su función solo cuando se ejecuta el servidor de ejecución (y no cuando se realizan migraciones, migraciones, shell, etc.) ) y desea evitar las excepciones AppRegistryNotReady que debe hacer de la siguiente manera:
expediente:
myapp/apps.py
fuente
Tenga en cuenta que no puede conectarse con fiabilidad a la base de datos o interactuar con modelos dentro de la
AppConfig.ready
función (consulte la advertencia en los documentos).Si necesita interactuar con la base de datos en su código de inicio, una posibilidad es utilizar la
connection_created
señal para ejecutar el código de inicialización al conectarse a la base de datos.Obviamente, esta solución es para ejecutar código una vez por conexión de base de datos, no una vez por inicio de proyecto. Por lo tanto, querrá un valor razonable para la
CONN_MAX_AGE
configuración para que no vuelva a ejecutar el código de inicialización en cada solicitud. También tenga en cuenta que el servidor de desarrollo ignoraCONN_MAX_AGE
, por lo que ejecutará el código una vez por solicitud en desarrollo.El 99% de las veces es una mala idea (el código de inicialización de la base de datos debe ir en migraciones), pero hay algunos casos de uso en los que no se puede evitar la inicialización tardía y las advertencias anteriores son aceptables.
fuente
my_receiver
función de desconectarse de laconnection_created
señal, en concreto, añadir lo siguiente a lamy_receiver
función:connection_created.disconnect(my_receiver)
.si desea imprimir "hello world" una vez cuando ejecute el servidor, ponga print ("hello world") fuera de clase StartupMiddleware
fuente