2009-07-04 10 views
10

quiero hacer algo después de haber prestado la vista utilizando¿Cómo haces algo después de renderizar la vista? (Django)

return render_to_response() 

son señales la única manera de hacer esto? ¿Debo escribir una señal personalizada o me pide que termine? ¿Me da suficiente información? Básicamente, necesito saber qué página se procesó y luego realizar una acción en respuesta a eso.

Gracias.

ACTUALIZACIÓN DE COMENTARIOS: No deseo mantener la presentación de la página, por lo que quiero mostrar la página primero y luego realizar la acción.

+2

Eso parece al revés. Sabes qué página estás por renderizar. Solo haz la acción. ¿Por qué no puedes simplemente insertar la acción extra en la función de vista? Proporcione alguna pista sobre lo que está tratando de hacer. –

+1

no quiero retrasar la presentación de la página, por lo que quiero mostrar la página primero y luego realizar la acción – rick

+0

@rick: por favor, no comentes tu propia pregunta, por favor actualiza tu pregunta con datos adicionales. –

Respuesta

-1

En el procesamiento para responder, pasa la página html que desea mostrar. Esa otra página debe enviar una publicación (a través de Javascript o algo similar) que desencadena la función correcta en sus vistas, luego esa vista llama a la siguiente página correcta para mostrar.

+0

Sí, eso funcionaría, pero me pregunto si hay una forma de hacerlo únicamente en el lado del servidor – rick

+0

No estoy seguro de que sea realmente posible:/ – AlbertoPL

+0

que definitivamente no se puede hacer desde el servidor. El servidor no sabe nada sobre lo que está haciendo el cliente, por lo que nunca sabrá que la página ha finalizado la representación. por supuesto, una publicación simple resolverá ese problema. – geowa4

4

Si tiene un proceso de larga duración, tiene dos opciones simples.

  1. Genera un subproceso antes de enviar la página de respuesta.

  2. Crea un "daemon de servicio en segundo plano" y pasa las solicitudes de trabajo a él.

Esto es todo fuera de Django. Utiliza subprocess o algún otro método de IPC para comunicarse con el otro proceso.

+1

De acuerdo - Usaría algún tipo de IPC para hacer que este servidor modular y de servidor web sea neutral. Probablemente no quieras hackear las partes internas de Django para hacer cosas después de que se envíe la respuesta. – cdleary

4

Una forma común de hacer esto es usar colas de mensajes. Coloca un mensaje en la cola y los hilos de trabajo (o procesos, etc.) consumen la cola y hacen el trabajo después de que su vista se haya completado.

Google App Engine tiene la cola de tareas api http://code.google.com/appengine/docs/python/taskqueue/, amazon tiene el servicio de cola simple http://aws.amazon.com/sqs/.

Una búsqueda rápida no mostró ninguna django pluggables que se parezcan a los estándares aceptados.

Una manera rápida y sucia de emular la funcionalidad es colocar el 'mensaje' en una tabla de base de datos, y hacer que un trabajo cron compruebe periódicamente la tabla para realizar el trabajo.

+0

+1 Una idea aún más eficiente que (con suerte) los mensajes ligeros de IPC. – cdleary

+0

Servicio de colas específicas de Django http://code.google.com/p/django-queue-service/ – agiliq

4

objeto HttpResponse de Django acepta un iterador en su constructor:

http://docs.djangoproject.com/en/dev/ref/request-response/#passing-iterators

por lo que podría hacer algo como:

def myiter(): 
    yield "my content" 
    enqueue_some_task() 
    return 

def myview(request): 
    return HttpResponse(myiter()) 

El uso normal de un iterador es enviar grandes cantidades de datos sin necesidad de leer todo en la memoria. Por ejemplo, lea fragmentos de un archivo y ceda apropiadamente. Nunca lo he usado de esta manera, pero parece que debería funcionar.

+1

Desafortunadamente, esto hará que la página parezca seguir cargando en el lado del cliente después de que se haya cargado por completo, ya que el servidor no cierra la conexión hasta que se produce el resultado final. – dionyziz

2

Mi solución favorita: un proceso separado que maneja tareas en segundo plano, típicamente cosas como indexar y enviar correos de notificación, etc. Y luego, durante el renderizado de vistas, envía un evento al sistema de manejo de eventos (no sé si Django tiene una integrada, pero siempre la necesita de todas formas, así que debería tener una) y el sistema par luego coloca un mensaje en una cola de mensajes (que es trivial para escribir a menos que tenga varias máquinas o múltiples procesos en segundo plano) que hace la tarea en cuestión.

10

Generas un hilo separado y haces que haga la acción.

t = threading.Thread(target=do_my_action, args=[my_argument]) 
# We want the program to wait on this thread before shutting down. 
t.setDaemon(False) 
t.start() 

Esto hará que 'do_my_action (my_argument)' para ser ejecutado en un segundo hilo que va a seguir trabajando incluso después de enviar su respuesta Django y termina el hilo inicial. Por ejemplo, podría enviar un correo electrónico sin demorar la respuesta.

+1

¡Una solución simple y funcional! –

+0

Intenté esta implementación. Aparentemente, el segundo subproceso iniciado finaliza incluso si su tarea aún no se ha completado. En mi caso, está actualizando varias entradas de BD – jaysonpryde

0

Quizás no entiendo su pregunta. Pero ¿por qué no algo simple como:

try: 
    return render_to_response() 
finally: 
    do_what_needs_to_be_done() 
+0

Una vez que se devuelve, la vista se renderizará ¿verdad? Independientemente de lo que está sucediendo en la sección de finalmente? Si es así, ¡esto es justo lo que necesito! – rick

+0

parece que no funciona. la representación se mantiene mientras el código en el final se está ejecutando. – rick

+2

Cuando hay una cláusula finally, el retorno de la función solo ocurre _después_ el código finalmente se ejecuta, por lo que esto no funcionará como se esperaba. – rslite

Cuestiones relacionadas