如何使用Django对HttpResponse进行流处理

时间:2022-10-04 20:22:50

I'm trying to get the 'hello world' of streaming responses working for Django (1.2). I figured out how to use a generator and the yield function. But the response still not streaming. I suspect there's a middleware that's mucking with it -- maybe ETAG calculator? But I'm not sure how to disable it. Can somebody please help?

我正在尝试为Django提供流响应的“hello world”(1.2)。我知道了如何使用生成器和屈服函数。但人们的反应仍不明朗。我怀疑有一个中间件在破坏它——可能是ETAG计算器?但我不知道如何禁用它。有人能帮忙吗?

Here's the "hello world" of streaming that I have so far:

这是我目前拥有的“你好世界”流媒体:

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)

2 个解决方案

#1


44  

You can disable the ETAG middleware using the condition decorator. That will get your response to stream back over HTTP. You can confirm this with a command-line tool like curl. But it probably won't be enough to get your browser to show the response as it streams. To encourage the browser to show the response as it streams, you can push a bunch of whitespace down the pipe to force its buffers to fill. Example follows:

可以使用条件decorator禁用ETAG中间件。这将使您的响应通过HTTP返回流。您可以使用像curl这样的命令行工具来确认这一点。但是,仅仅让浏览器在流时显示响应是不够的。为了鼓励浏览器在流时显示响应,您可以向管道下推一堆空白,以强制其缓冲区填充。例子如下:

from django.views.decorators.http import condition

@condition(etag_func=None)
def stream_response(request):
    resp = HttpResponse( stream_response_generator(), content_type='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"

#2


34  

A lot of the django middleware will prevent you from streaming content. Much of this middleware needs to be enabled if you want to use the django admin app, so this can be an annoyance. Luckily this has been resolved in the django 1.5 release. You can use the StreamingHttpResponse to indicate that you want to stream results back and all the middleware that ships with django is aware of this and acts accordingly to not buffer your content output but send it straight down the line. Your code would then look like the following to use the new StreamingHttpResponse object.

许多django中间件将阻止您流媒体内容。如果您想要使用django管理应用程序,那么需要启用许多中间件,因此这可能是一个麻烦。幸运的是,django 1.5已经解决了这个问题。您可以使用StreamingHttpResponse来指示您想要将结果流回,并且与django一起发布的所有中间件都意识到了这一点,因此不缓冲您的内容输出,而是直接将其发送到行中。然后,您的代码将像下面这样使用新的StreamingHttpResponse对象。

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 on Apache

注意在Apache

I tested the above on Apache 2.2 with Ubuntu 13.04. The apache module mod_deflate which was enabled by default in the setup I tested will buffer the content you are trying to stream until it reaches a certain block size then it will gzip the content and send it to the browser. This will prevent the above example from working as desired. One way to avoid this is to disable mod_deflate by putting the following line in your apache configuration:

我在Apache 2.2上使用Ubuntu 13.04测试了上述功能。在我测试的设置中默认启用的apache模块mod_deflate会缓冲您试图流的内容,直到它达到一定的块大小,然后它将压缩内容并将其发送到浏览器。这将阻止上面的示例按需要工作。避免这种情况的一种方法是通过在apache配置中放置以下行来禁用mod_deflate:

SetEnvIf Request_URI ^/mysite no-gzip=1

This is discussed more in the How to disable mod_deflate in apache2? question.

如何在apache2中禁用mod_deflate ?的问题。

#1


44  

You can disable the ETAG middleware using the condition decorator. That will get your response to stream back over HTTP. You can confirm this with a command-line tool like curl. But it probably won't be enough to get your browser to show the response as it streams. To encourage the browser to show the response as it streams, you can push a bunch of whitespace down the pipe to force its buffers to fill. Example follows:

可以使用条件decorator禁用ETAG中间件。这将使您的响应通过HTTP返回流。您可以使用像curl这样的命令行工具来确认这一点。但是,仅仅让浏览器在流时显示响应是不够的。为了鼓励浏览器在流时显示响应,您可以向管道下推一堆空白,以强制其缓冲区填充。例子如下:

from django.views.decorators.http import condition

@condition(etag_func=None)
def stream_response(request):
    resp = HttpResponse( stream_response_generator(), content_type='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"

#2


34  

A lot of the django middleware will prevent you from streaming content. Much of this middleware needs to be enabled if you want to use the django admin app, so this can be an annoyance. Luckily this has been resolved in the django 1.5 release. You can use the StreamingHttpResponse to indicate that you want to stream results back and all the middleware that ships with django is aware of this and acts accordingly to not buffer your content output but send it straight down the line. Your code would then look like the following to use the new StreamingHttpResponse object.

许多django中间件将阻止您流媒体内容。如果您想要使用django管理应用程序,那么需要启用许多中间件,因此这可能是一个麻烦。幸运的是,django 1.5已经解决了这个问题。您可以使用StreamingHttpResponse来指示您想要将结果流回,并且与django一起发布的所有中间件都意识到了这一点,因此不缓冲您的内容输出,而是直接将其发送到行中。然后,您的代码将像下面这样使用新的StreamingHttpResponse对象。

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 on Apache

注意在Apache

I tested the above on Apache 2.2 with Ubuntu 13.04. The apache module mod_deflate which was enabled by default in the setup I tested will buffer the content you are trying to stream until it reaches a certain block size then it will gzip the content and send it to the browser. This will prevent the above example from working as desired. One way to avoid this is to disable mod_deflate by putting the following line in your apache configuration:

我在Apache 2.2上使用Ubuntu 13.04测试了上述功能。在我测试的设置中默认启用的apache模块mod_deflate会缓冲您试图流的内容,直到它达到一定的块大小,然后它将压缩内容并将其发送到浏览器。这将阻止上面的示例按需要工作。避免这种情况的一种方法是通过在apache配置中放置以下行来禁用mod_deflate:

SetEnvIf Request_URI ^/mysite no-gzip=1

This is discussed more in the How to disable mod_deflate in apache2? question.

如何在apache2中禁用mod_deflate ?的问题。