2009-09-03 16 views
6

Invio una richiesta AJAX a una vista Django che potrebbe richiedere molto tempo. Passa attraverso alcuni passaggi ben definiti, tuttavia, quindi vorrei stampare gli indicatori di stato per l'utente facendogli sapere quando è finito di fare una certa cosa e si è trasferito a quella successiva.Django - risposta a livello?

Se stavo usando il PHP potrebbe assomigliare a questo, utilizzando la funzione flush:

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

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

Come potrei fare per fare lo stesso con Django? Guardando a the documentation Vedo che gli oggetti HttpResponse hanno un metodo flush, ma tutto ciò che ha da dire è che "Questo metodo rende un'istanza HttpResponse un oggetto simile a un file". - Non sono sicuro che sia quello che voglio. Sto attraversando un periodo difficile per capire come ciò potrebbe essere fatto in Django, dal momento che devo restituire la risposta e in realtà non ho il controllo su quando il contenuto va nel browser.

risposta

8

La maggior parte dei server Web (ad esempio FCGI/SCGI) esegue il proprio buffering, i client HTTP eseguono il proprio e così via. È molto difficile ottenere effettivamente i dati svuotati in questo modo e che il client lo possa effettivamente ricevere, perché non è un'operazione tipica.

Il più vicino a ciò che si sta tentando di fare sarebbe passare un iteratore a HttpResponse e fare il lavoro in un generatore; qualcosa di simile:

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()) 

... ma questo non sarà necessariamente filo. (Codice non testato, ma si ottiene l'idea, vedere http://docs.djangoproject.com/en/dev/ref/request-response/#passing-iterators.)

La maggior parte dell'infrastruttura non si aspetta semplicemente una risposta frammentaria. Anche se Django non esegue il buffering, il tuo server front-end potrebbe essere, e probabilmente lo è anche il client. Ecco perché la maggior parte delle cose usa pull updates per questo: un'interfaccia separata per interrogare lo stato di una richiesta di lunga durata.

(mi piacerebbe essere in grado di fare gli aggiornamenti push affidabili per questo genere di cose, troppo ...)

+0

Grazie. Avevo provato i generatori, ma stupidamente stavo dando interi nel mio test e non ha funzionato. Probabilmente finirò per non farlo affatto, ma è bello sapere che almeno ha funzionato, anche se con le limitazioni che hai menzionato. –

4

non sono sicuro è necessario utilizzare la funzione() a filo.

La tua richiesta AJAX dovrebbe solo andare a una vista di Django.

Se i passaggi possono essere suddivisi, mantenerlo semplice e creare una vista per ogni passaggio. In questo modo, una volta completato un processo, è possibile aggiornare l'utente e avviare la richiesta successiva tramite AJAX.

views.py

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

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

In molti casi questo non è voluto, però. Se l'intera operazione è un'unità, allora aggiunge un ritardo non necessario tra ogni fase che inizia (in attesa che il client lo faccia partire); questo è peggio se si vogliono fare aggiornamenti più precisi (ad esempio, la percentuale completa). È possibile che l'intera operazione venga eseguita in un'unica transazione di database; anche se così non fosse, potresti voler ripulire se l'intera operazione non è completata, il che implica che è necessario anche un timeout per interrompere se il client scompare. Certo, dipende da cosa stai facendo. –

+0

Sono d'accordo, dipende dalla struttura e dalle aspettative del risultato. – monkut

+0

Ho pensato di dividerlo, ma per le ragioni sopra citate e poi alcuni speravo davvero di evitarlo. Tuttavia, tutti i passaggi sono indipendenti al 100%, ma non esiste un limite di 2 richieste attive per dominio o qualcosa del genere? –

Problemi correlati