55 votes

Comment diffuser une réponse HttpResponse avec Django

J'essaie d'obtenir le «bonjour monde» des réponses en continu qui fonctionne pour Django (1.2). J'ai compris comment utiliser un générateur et la fonction yield . Mais la réponse n'est toujours pas en streaming. Je soupçonne qu’il existe un middleware qui s’emballe - peut-être une calculatrice ETAG? Mais je ne sais pas comment le désactiver. Quelqu'un peut-il aider s'il vous plaît?

Voici le "bonjour le monde" du streaming que j'ai jusqu'à présent:

 def stream_response(request):
    resp = HttpResponse( stream_response_generator())
    return resp

def stream_response_generator():
    for x in range(1,11):
        yield "%s\n" % x  # Returns a chunk of the response to the browser
        time.sleep(1)
 

46voto

Leopd Points 12652

Vous pouvez désactiver l'ETAG middleware à l'aide de la condition de décorateur. Qui permettra à votre réponse à revenir sur HTTP. Vous pouvez le vérifier avec un outil en ligne de commande comme curl. Mais il ne sera probablement pas suffisant pour obtenir votre navigateur pour montrer la réaction des ruisseaux. Pour encourager le navigateur pour afficher la réaction des flux, vous pouvez pousser un tas de blanc en bas du tuyau à la force de ses tampons à remplir. L'exemple qui suit:

from django.views.decorators.http import condition

@condition(etag_func=None)
def stream_response(request):
    resp = HttpResponse( stream_response_generator(), mimetype='text/html')
    return resp

def stream_response_generator():
    yield "<html><body>\n"
    for x in range(1,11):
        yield "<div>%s</div>\n" % x
        yield " " * 1024  # Encourage browser to render incrementally
        time.sleep(1)
    yield "</body></html>\n"

39voto

Marwan Alsabbagh Points 4245

Beaucoup de django middleware va vous empêcher de diffusion en continu de contenu. Une grande partie de ce middleware doit être activé si vous souhaitez utiliser l'admin de django app, donc cela peut être une gêne. Heureusement, ce problème a été résolu dans la django 1.5 libérer. Vous pouvez utiliser le StreamingHttpResponse pour indiquer que vous souhaitez diffuser les résultats et toutes les middleware qui est livré avec django est conscient de cela et agit en conséquence à pas de tampon de votre sortie contenu, mais de l'envoyer directement vers le bas de la ligne. Votre code devrait ressembler à la suivante pour utiliser le nouveau StreamingHttpResponse objet.

def stream_response(request):
    return StreamingHttpResponse(stream_response_generator())

def stream_response_generator():
    for x in range(1,11):
        yield "%s\n" % x  # Returns a chunk of the response to the browser
        time.sleep(1)

Note sur Apache

J'ai testé le dessus de Apache 2.2 avec Ubuntu 13.04. L'apache module mod_deflate qui a été activée par défaut dans la configuration que je le test de la mémoire tampon le contenu que vous essayez de flux jusqu'à ce qu'il atteint une certaine taille de bloc, alors il sera de gzip le contenu et l'envoyer au navigateur. Cela permettra d'éviter l'exemple ci-dessus, de fonctionner comme souhaité. Une manière d'éviter cela est de désactiver le mod_deflate en insérant la ligne suivante dans votre configuration d'apache:

SetEnvIf Request_URI ^/mysite no-gzip=1

Cette question est examinée plus dans la Façon de désactiver mod_deflate dans apache2? question.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X