Django调试工具栏:如何对文件下载进行性能分析?

9
我的Django Web应用程序允许用户即时下载生成的文本文件:
response = HttpResponse(my_file_contents)
response['Content-Disposition'] = 'attachment; filename="my file.txt"'
return response

我安装了Django Debug Toolbar(版本为0.11.0,因为1.0.1不能正常工作),但是当我点击下载时,工具栏没有显示有关已下载文件的信息,可能是因为这是一个单独的页面/请求(或者可能是因为这是一个非HTML文件)。下载的文件也不包含任何调试信息。我该如何对此文件下载的性能进行分析?

相关内容:https://dev59.com/cmUq5IYBdhLWcg3wSelm - djvg
4个回答

5
如果你专注于分析数据库查询,一种替代临时解决方案是不返回文件下载响应,而是加载一个模板(在你的应用程序中任何有效的Django模板都可以使用)。DDT仍然记录所有查询,你可以在随后的页面上看到它们。这个方法的原因是通常你感兴趣的是为了准备下载数据而进行的查询。将手头上的一些数据转换成响应的实际过程通常非常快。
假设你有一个表单,可以请求下载。通常你的视图会返回像这样的东西:
# (Do something here to collect data)
response = HttpResponse(export_data, content_type=content_type)
response['Content-Disposition'] = 'attachment; filename=somefile.txt'
return response

只需将其注释掉并返回常规渲染的模板即可,如果不想显示数据,则无需显示数据。如果使用像TemplateView或FormView这样的mixin,可能只需要注释上面的内容,然后Django将呈现模板,就好像未执行下载操作一样。或者,在应用程序中渲染任何Django模板。现在,打开DDT工具栏--那里有您的所有查询!


这可以使用自定义中间件来自动化。 - djvg

1
您说得对,这是调试工具栏无法帮助您的情况之一。我建议使用日志文件来计时请求时间。例如,如果您正在使用Nginx,则可以使用其语法将额外信息添加到日志文件。例如,以下行将为每个请求添加响应时间:
log_format timed_combined '$remote_addr - $remote_user [$time_local]  '
      '"$request" $status $body_bytes_sent '
      '"$http_referer" "$http_user_agent" '
      '$request_time $upstream_response_time $gzip_ratio';

如果你更喜欢Django应用程序的解决方案,可以查看django-timelog

1
你可以使用django-debug-toolbar-force
它允许你通过添加?debug-toolbar来强制渲染任何url的模板。
这样,你就可以在开发过程中访问工具栏及其所有仪器,而无需进行任何代码更改。
注意:截至目前,我不确定它是否有积极维护,最后一次提交是在2020年。

0

@timothyashaw的回答很有道理,但它需要临时修改代码。

或者,我们可以编写一个中间件来捕获所有“文件”响应并返回虚拟响应。Django-debug-toolbar方便地提供了Panel类,这样我们就可以通过DjDT工具栏轻松地切换我们的中间件的开启关闭状态。

以下示例基本上是默认"拦截重定向"面板的修改版本:

from debug_toolbar.panels import Panel
from django.http import HttpResponse


class FileInterceptsPanel(Panel):
    has_content = False
    title = 'Intercept files'

    def process_request(self, request):
        """If the response contains a file, replace it by a dummy response"""
        response = super().process_request(request)
        response_is_file = ...  # use whatever test suits your case
        if response_is_file:
            response = HttpResponse('<body>debug file response</body>')
        return response

一旦配置完成,您将在DjDT工具栏中看到类似于以下内容:

panel example

一些注记:

  • 应该将FileInterceptsPanel插入到settings.py中的DEBUG_TOOLBAR_PANELS中,如文档所述。

  • FileInterceptsPanel默认情况下将启用,但您可以将其添加到settings.py中的DEBUG_TOOLBAR_CONFIG['DISABLE_PANELS']以默认禁用它。

  • response_is_file测试取决于您的具体用例。在OP的示例中,它可能类似于'attachment' in response.get('Content-Disposition', '')。或者,我们可以例如测试FileResponseStreamingHttpResponseJsonResponse的实例,或测试response.streaming

  • 如果您正在捕获JsonResponse实例,请注意django-debug-toolbar也使用这些进行详细面板。例如,可以通过测试b'djdt' not in response.content来排除这些内容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接