如何使用Django流式传输HttpResponse

muu*_*ope 54 python django streaming

我正在尝试为Django(1.2)提供流媒体响应的"hello world".我想出了如何使用发电机和yield功能.但响应仍然不流.我怀疑有一个中间件正在捣乱它 - 也许是ETAG计算器?但我不知道如何禁用它.有人可以帮忙吗?

这是我到目前为止流媒体的"你好世界":

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)
Run Code Online (Sandbox Code Playgroud)

Leo*_*opd 46

您可以使用条件装饰器禁用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"
Run Code Online (Sandbox Code Playgroud)

  • 在我的测试中,Django GZipMiddleware可以防止这种情况发生. (3认同)

Mar*_*agh 38

很多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)
Run Code Online (Sandbox Code Playgroud)

关于Apache的注意事项

我使用Ubuntu 13.04在Apache 2.2上测试了上述内容.在我测试的设置中默认启用的apache模块mod_deflate将缓冲您尝试流式传输的内容,直到达到某个块大小,然后它将gzip内容并将其发送到浏览器.这将阻止上述示例按预期工作.避免这种情况的一种方法是通过在apache配置中添加以下行来禁用mod_deflate:

SetEnvIf Request_URI ^/mysite no-gzip=1
Run Code Online (Sandbox Code Playgroud)

这将在如何在apache2中禁用mod_deflate中进行更多讨论.题.