Python Django:显示在每页上加载一页所花费的时间

Python Django:显示在每页上加载一页所花费的时间,python,django,Python,Django,在Django中,如何返回在站点的每个页面中加载页面所花费的时间(而不是日期),而不必在每个视图中写入。py类似于以下代码的代码 start = time.time() #model operations loadingpagetime = time.time() - start 如果使用模板\u上下文\u处理器是最佳选择。 我如何从那里获得整个页面加载时间,而不是仅仅获得模板加载时间 更新: 由于最初的问题似乎还不够清楚,这里有一个方法来说明我想要做的Python版本 #!/usr/bin/

在Django中,如何返回在站点的每个页面中加载页面所花费的时间(而不是日期),而不必在每个视图中写入。py类似于以下代码的代码

start = time.time()
#model operations
loadingpagetime = time.time() - start
如果使用
模板\u上下文\u处理器
是最佳选择。
我如何从那里获得整个页面加载时间,而不是仅仅获得模板加载时间

更新:

由于最初的问题似乎还不够清楚,这里有一个方法来说明我想要做的Python版本

#!/usr/bin/env python
import cgitb; cgitb.enable() 
import time
print 'Content-type: text/html\n\n'

start = time.time()

print '<html>'
print '<head>'
print '</head>'
print '<body>'
print '<div>HEADER</div>'
print '<div>'
print '<p>Welcome to my Django Webpage!</p>'
print '<p>Welcome to my Django Webpage!</p>'
print '<p>Welcome to my Django Webpage!</p>'
print '</div>'

time.sleep(3)
loadingtime = time.time() - start

print '<div>It took ',loadingtime,' seconds to load the page</div>'
print '</body>'
print '</html>'
#/usr/bin/env python
进口cgib;cgib.enable()
导入时间
打印“内容类型:text/html\n\n”
开始=时间。时间()
打印“
打印“
打印“
打印“
打印“标题”
打印“
打印“欢迎访问我的Django网页

" 打印“欢迎访问我的Django网页

" 打印“欢迎访问我的Django网页

" 打印“ 时间。睡眠(3) loadingtime=time.time()-开始 打印“加载时间”、“加载页面花费的时间”和“秒” 打印“ 打印“
您可以创建自定义日志来记录此操作。下面是我如何创建一个中间件来实现这个目的(我稍微修改了代码)

首先,假设您的项目有一个名称:
test\u project
,创建一个文件名
middleware.py
,我将它放在与
settings.py
相同的文件夹中:

from django.db import connection
from time import time
from operator import add
import re


class StatsMiddleware(object):

    def process_view(self, request, view_func, view_args, view_kwargs):
        '''
        In your base template, put this:
        <div id="stats">
        <!-- STATS: Total: %(total_time).2fs Python: %(python_time).2fs DB: %(db_time).2fs Queries: %(db_queries)d ENDSTATS -->
        </div>
        '''

        # Uncomment the following if you want to get stats on DEBUG=True only
        #if not settings.DEBUG:
        #    return None

        # get number of db queries before we do anything
        n = len(connection.queries)

        # time the view
        start = time()
        response = view_func(request, *view_args, **view_kwargs)
        total_time = time() - start

        # compute the db time for the queries just run
        db_queries = len(connection.queries) - n
        if db_queries:
            db_time = reduce(add, [float(q['time'])
                                   for q in connection.queries[n:]])
        else:
            db_time = 0.0

        # and backout python time
        python_time = total_time - db_time

        stats = {
            'total_time': total_time,
            'python_time': python_time,
            'db_time': db_time,
            'db_queries': db_queries,
        }

        # replace the comment if found
        if response and response.content:
            s = response.content
            regexp = re.compile(r'(?P<cmt><!--\s*STATS:(?P<fmt>.*?)ENDSTATS\s*-->)')
            match = regexp.search(s)
            if match:
                s = (s[:match.start('cmt')] +
                     match.group('fmt') % stats +
                     s[match.end('cmt'):])
                response.content = s

        return response
    # replace the comment if found
    if response:
        try:
            # detects TemplateResponse which are not yet rendered
            if response.is_rendered:
                rendered_content = response.content
            else:
                rendered_content = response.rendered_content
        except AttributeError:  # django < 1.5
            rendered_content = response.content
        if rendered_content:
            s = rendered_content
            regexp = re.compile(
                r'(?P<cmt><!--\s*STATS:(?P<fmt>.*?)ENDSTATS\s*-->)'
            )
            match = regexp.search(s)
            if match:
                s = (s[:match.start('cmt')] +
                     match.group('fmt') % stats +
                     s[match.end('cmt'):])
                response.content = s

    return response
注意:您必须像上面那样向中间件类添加完整路径,格式为:

<project_name>.<middleware_file_name>.<middleware_class_name>
注意:您可以随意命名
并对该div使用CSS,但不要更改注释
。如果要更改它,请确保在创建的
middleware.py
中根据正则表达式模式对其进行测试

瞧,享受这些统计数据吧

编辑:

对于那些经常使用CBV(基于类的视图)的人来说,使用上述解决方案可能会遇到错误
contentnotrendererror
。别担心,这是
中间件中的修复程序。py

from django.db import connection
from time import time
from operator import add
import re


class StatsMiddleware(object):

    def process_view(self, request, view_func, view_args, view_kwargs):
        '''
        In your base template, put this:
        <div id="stats">
        <!-- STATS: Total: %(total_time).2fs Python: %(python_time).2fs DB: %(db_time).2fs Queries: %(db_queries)d ENDSTATS -->
        </div>
        '''

        # Uncomment the following if you want to get stats on DEBUG=True only
        #if not settings.DEBUG:
        #    return None

        # get number of db queries before we do anything
        n = len(connection.queries)

        # time the view
        start = time()
        response = view_func(request, *view_args, **view_kwargs)
        total_time = time() - start

        # compute the db time for the queries just run
        db_queries = len(connection.queries) - n
        if db_queries:
            db_time = reduce(add, [float(q['time'])
                                   for q in connection.queries[n:]])
        else:
            db_time = 0.0

        # and backout python time
        python_time = total_time - db_time

        stats = {
            'total_time': total_time,
            'python_time': python_time,
            'db_time': db_time,
            'db_queries': db_queries,
        }

        # replace the comment if found
        if response and response.content:
            s = response.content
            regexp = re.compile(r'(?P<cmt><!--\s*STATS:(?P<fmt>.*?)ENDSTATS\s*-->)')
            match = regexp.search(s)
            if match:
                s = (s[:match.start('cmt')] +
                     match.group('fmt') % stats +
                     s[match.end('cmt'):])
                response.content = s

        return response
    # replace the comment if found
    if response:
        try:
            # detects TemplateResponse which are not yet rendered
            if response.is_rendered:
                rendered_content = response.content
            else:
                rendered_content = response.rendered_content
        except AttributeError:  # django < 1.5
            rendered_content = response.content
        if rendered_content:
            s = rendered_content
            regexp = re.compile(
                r'(?P<cmt><!--\s*STATS:(?P<fmt>.*?)ENDSTATS\s*-->)'
            )
            match = regexp.search(s)
            if match:
                s = (s[:match.start('cmt')] +
                     match.group('fmt') % stats +
                     s[match.end('cmt'):])
                response.content = s

    return response
#如果找到注释,请替换
如果回答:
尝试:
#检测尚未呈现的TemplateResponse
如果response.u被呈现:
呈现内容=response.content
其他:
呈现内容=响应。呈现内容
除属性错误外:#django<1.5
呈现内容=response.content
如果呈现内容:
s=渲染内容
regexp=re.compile(
r'(?P)'
)
match=regexp.search
如果匹配:
s=(s[:match.start('cmt')]+
match.group('fmt')%stats+
s[match.end('cmt'):])
response.content=s
返回响应

我使用Django 1.6.x获得了它,如果您对Django的其他版本有问题,请在评论部分ping我。

如果您想向访问者显示页面加载信息,Hieu Nguyen的回答将是一个很好的选择。但我也向你推荐一些好的工具

因此,如果您仅仅出于开发目的需要这些数据,请查看。它将附加一个很好的工具栏,其中包含每个页面的有用统计信息,包括数据库查询、模板呈现等所花费的时间

最后,如果您需要Djagno的专业评测工具,这可能是一个非常好的选择。

为您提供了请求周期中发生的所有事情的详细分析。它是一个中间件,可以生成一个完整的调用树,精确地显示每个函数的运行情况和花费的时间

看起来是这样的:

我强烈推荐它
:)


图片来源:

我可能错了,但我记得的第一件事是document.ready和ajax。。。 我不认为这是最好的解决方案,但它应该非常简单,不仅可以在django中实现,还可以在其他任何地方实现。 在视图中处理请求时,启动计时器,触发document.ready时,进行ajax调用以停止计时器。
但是我应该承认@Hieu-Nguyen非常出色)

我升级了middleware.py。简单地说,我们在基本模板中添加了一些独特的文本,然后在中间件进程_响应中替换它。这个方法看起来有点棘手,但我们的生成时间更接近于真值,而且javascript没有问题。客户端上的Javascript不能在第一个加载的页面上使用页面标题,只有创建XHR对象,然后获取页面


您可以在模板中写出占位符,然后在中间件中修改它。然而,任何在您的中间件之后运行的中间件都可能需要任意数量的时间,因此这不是一个精确的计数。如果您想更准确地完成此操作,请在Django前面的负载平衡器、反向代理或其他任何程序中进行重写。@JamesAylett如果您能给出答案/示例,将不胜感激。抱歉,没有时间将其写出来-中间件需要一点时间来编写和测试。祝你好运好的,这里有一个潜在的问题。在呈现模板时,请求仍在继续。从请求开始到呈现该模板片段所经过的时间是可行的,但如果一段响应中间件阻塞30秒,则无法将该数据包含在已呈现的HTML中。正如@JamesAylett所说,中间件使用的占位符是最接近的占位符,但是有很多警告。请参阅django调试工具栏的源代码。中间件模块和TimerDebugPanel了解起点。处理其他中间件类所花费的时间如何?我已经在上面的回答中提到过,请仔细阅读。针对每个响应编译和运行正则表达式是一个显著的性能影响。至少,将编译后的版本缓存在中间件中。@HieuNguyen如何使其与基于类的视图一起工作?继续