Просмотр SQL запросов, сделанных Django ORM

Частая задача, которая встаёт при использовании Django в серьёзных проектах — знать, какие именно запросы генерирует Django ORM. Неподготовленного человека просмотр этих SQL запросов (вернее их количества) может привести в шок ) Например, если поле объекта является ForeignKey(null=True), то при выводе этого поля у множества объектов, на каждый объект будет делаться запрос для этого поля и даже select_related() не поможет. Подобные проблемы решаются различными ухищрениями типа: — http://web-brains.com/2007/12/06/selecte_related_and_foreign_key/http://piranha.org.ua/blog/2007/10/31/related-objects/ Но рассказать я хочу не про ухищрения, о которых и так уже рассказано, а о том, как можно удобно просматривать SQL запросы для каждой конкретной страницы сайта, сделанного на Django. Решение очевидно: надо сделать templatetag, который, будет выводить эти запросы ) Как гласит официальная документация запросы, которые сделал django ORM, можно извлечь из django.db.connection.queries (settings.DEBUG должен быть True). Т.е. логика template tag получается очень простой: получить sql запросы и передать их в шаблон. Конечно, если выводить полотно чёрнобелых запросов на каждой странице, это будет неэстетично и утомительно для мозга, поэтому я сделал несколько плюшек: разбивание длинных строк запроса на несколько строк, подсветка через pygments (опционально), скрытие блока запросов по умолчание и показ их по щелчку на специальной ссылке. Код в студию! Логика тэга orm_debug:

@register.inclusion_tag('site/orm_debug.html')
def orm_debug():
    import re
    try:
        from pygments import highlight
        from pygments.lexers import SqlLexer
        from pygments.formatters import HtmlFormatter
        pygments_installed = True
    except ImportError:
        pygments_installed = False

    from django.db import connection
    queries = connection.queries
    query_time = 0
    query_count = 0
    for query in queries:
        query_time += float(query['time'])
        query_count += int(1)
        query['sql'] = re.sub(r'(FROM|WHERE)', '\n\\1', query['sql'])
        query['sql'] = re.sub(r'((?:[^,]+,){3})', '\\1\n    ', query['sql'])
        if pygments_installed:
            formatter = HtmlFormatter()
            query['sql'] = highlight(query['sql'], SqlLexer(), formatter)
            pygments_css = formatter.get_style_defs()
        else:
            pygments_css = ''
    return {
        'pygments_css': pygments_css,
        'pygments_installed': pygments_installed,
        'query_time': query_time,
        'query_count': query_count,
        'queries': queries}
Шаблон тэга orm_debug:

<style type="text/css">
{% if pygments_css %}
{{ pygments_css }}
{% endif %}
#orm-debug-body {
    display: none;
    color: #e0e0e0;
    background-color: #101010;
    font-size: 15px;
    line-height: 16px;
    padding: 1px 1em 1em 1em;
}
#orm-debug-body p {
    margin: 0;
}
#orm-debug-body pre {
    margin: 0;
}
#orm-debug-body .query-info {
    margin-top: 1em;
    margin-bottom: 0.2em;
}
</style>
<div id="orm-debug-head">
    <a href="#" onclick="document.getElementById('orm-debug-body').style.display = 'block'">debug</a>
    sql count: {{ query_count }}, sql time: {{ query_time }}
</div>
<div id="orm-debug-body">
{% for query in queries %}
<div class="code">
    <div class="query-info">time: {{ query.time }}</div>
    {% if not pygments_installed %}<pre>{% endif %}
    {{ query.sql|safe|linebreaks }}
    {% if not pygments_installed %}</pre>{% endif %}
</div>
{% endfor %}
</div>
Как использовать этот тэг? Очень просто: кладёте куда надо, подключаете, потом в шаблоне страницы в самом-самом низу пишете {% orm_debug %}. В этом месте появится ссылочка, а также инфа по суммарному времени и количестве запросов. После щелчка на ссылке будет отрываться блок SQL запросов. UPD: Актуальный orm_debug тэг доступен в приложении django-debug по адресу http://bitbucket.org/lorien/django-debug
Add post to:   Delicious Reddit Slashdot Digg Technorati Google
Make comment

Comments

Как я уже сказал на форуме у Ивана, очень зачётная вещь. Всё просто и доступно. +1

На самом деле я к этой штуке успел ещё одну мега вещь прикрутить, попозже статью переделаю. В общем, через AJAX можно смотреть explain каждого SQL-запроса )

Жду с нетерпением …

Спасибо, очень пригодилось.

..bw

как этим пользоваться так и не понял.. ((

Required. 30 chars of fewer.

Required.

captcha image Please, enter symbols, which you see on the image