2009-09-03 8 views
6

Estoy enviando una solicitud de AJAX a una vista de Django que potencialmente puede llevar mucho tiempo. Sin embargo, sigue algunos pasos bien definidos, por lo que me gustaría imprimir los indicadores de estado para el usuario, haciéndole saber cuándo ha terminado de hacer algo y ha pasado al siguiente.Django - respuesta de color?

Si yo estaba usando PHP que podría tener este aspecto, el uso de la función flush:

do_something(); 
print 'Done doing something!'; 
flush(); 

do_something_else(); 
print 'Done doing something else!'; 
flush(); 

¿Cómo voy a ir haciendo lo mismo con Django? En cuanto a the documentation Veo que los objetos HttpResponse tienen un método de descarga, pero todo lo que tiene que decir es que "Este método hace que una instancia de HttpResponse sea un objeto similar a un archivo". - No estoy seguro de que eso es lo que quiero. Me está costando trabajo entender cómo se podría hacer esto en Django, ya que tengo que devolver la respuesta y realmente no tengo control sobre cuándo el contenido va al navegador.

Respuesta

8

La mayoría de los servidores web (por ejemplo, FCGI/SCGI) hacen su propio almacenamiento en búfer, los clientes HTTP los hacen, y así sucesivamente. Es muy difícil obtener datos eliminados de esta manera y que el cliente realmente los reciba, porque no es una operación típica.

Lo más cercano a lo que intenta hacer sería pasar un iterador a HttpResponse, y hacer el trabajo en un generador; algo como esto:

def index(request): 
    def do_work(): 
     step_1() 
     yield "step 1 complete" 
     step_2() 
     yield "step 2 complete" 
     step_3() 
     yield "step 3 complete" 
    return HttpResponse(do_work()) 

... pero esto no necesariamente ras. (Código no probado, pero tiene la idea; consulte http://docs.djangoproject.com/en/dev/ref/request-response/#passing-iterators.)

La mayor parte de la infraestructura simplemente no espera una respuesta por partes. Incluso si Django no está almacenando en búfer, su servidor de aplicaciones para el usuario podría estarlo, y el cliente probablemente también lo esté. Es por eso que la mayoría de las cosas usan actualizaciones de extracción para esto: una interfaz separada para consultar el estado de una solicitud de larga ejecución.

(Me gustaría ser capaz de hacer actualizaciones de inserción fiables para este tipo de cosas, también ...)

+0

Gracias. Probé con generadores pero, estúpidamente, estaba dando números enteros en mi prueba y no funcionó. Probablemente termine haciendo esto, pero es bueno saber que al menos funcionó, aunque con las limitaciones que mencionaste. –

4

no estoy seguro de lo que necesita para utilizar la función() al ras.

Su solicitud AJAX solo debe ir a una vista django.

Si sus pasos se pueden desglosar, manténgalo simple y cree una vista para cada paso. De esta forma, uno de los procesos finaliza, puede actualizar al usuario y comenzar la próxima solicitud a través de AJAX.

views.py

def do_something(request): 
    # stuff here 
    return HttpResponse() 

def do_something_else(request): 
    # more stuff 
    return HttpResponse() 
+0

En muchos casos, esto no se quiere, sin embargo. Si toda la operación es una unidad, entonces está agregando un retraso innecesario entre cada inicio de la fase (esperando que el cliente lo inicie); esto es peor si desea hacer actualizaciones más finas (por ej., porcentaje completado). Toda la operación puede querer ejecutarse en una única transacción de base de datos; incluso si no lo hace, es posible que desee limpiar si no se completa toda la operación, lo que implica que también necesita un tiempo de espera para abortar si el cliente desaparece. Por supuesto, depende de lo que estés haciendo. –

+0

Acepto, depende de la estructura y las expectativas del resultado. – monkut

+0

Consideré dividirlo, pero por las razones mencionadas anteriormente y luego algunas realmente esperaba evitarlo. Sin embargo, todos los pasos son 100% independientes, pero ¿no hay un límite de 2 solicitudes activas por dominio o algo así? –

Cuestiones relacionadas