如何使用django-debug-toolbar for django-tastypie?

时间:2013-01-31 03:57:22

标签: django debugging tastypie

django-debug-toolbar需要输出为html,但是django-tastypie的默认输出格式是json。

我尝试发送http://localhost/api/v1/resource/?format=html,但它说Sorry, not implemented yet. Please append "?format=json" to your URL

即使此文档将html列为有效选项之一,它也会在TODO list上说明 http://django-tastypie.readthedocs.org/en/latest/serialization.html#to-html

如何使用调试工具栏调试tastypie api调用?
(例如,我想看看为api调用运行了多少个sql查询..等等)

也许我可以从django视图中调用api但是如何?

8 个答案:

答案 0 :(得分:35)

这是我为类似目的编写的中间件,它将HTML中的json包装起来以启用调试工具栏并且还可以打印它。此外,它支持二进制数据。我没有使用tastypie,但我认为它也应该适用。

# settings-dev.py
from django.http import HttpResponse
import json   

MIDDLEWARE_CLASSES += (
    'debug_toolbar.middleware.DebugToolbarMiddleware',
    'NonHtmlDebugToolbarMiddleware',
)

class NonHtmlDebugToolbarMiddleware(object):
    """
    The Django Debug Toolbar usually only works for views that return HTML.
    This middleware wraps any non-HTML response in HTML if the request
    has a 'debug' query parameter (e.g. http://localhost/foo?debug)
    Special handling for json (pretty printing) and
    binary data (only show data length)
    """

    @staticmethod
    def process_response(request, response):
        if request.GET.get('debug') == '':
            if response['Content-Type'] == 'application/octet-stream':
                new_content = '<html><body>Binary Data, ' \
                    'Length: {}</body></html>'.format(len(response.content))
                response = HttpResponse(new_content)
            elif response['Content-Type'] != 'text/html':
                content = response.content
                try:
                    json_ = json.loads(content)
                    content = json.dumps(json_, sort_keys=True, indent=2)
                except ValueError:
                    pass
                response = HttpResponse('<html><body><pre>{}'
                                        '</pre></body></html>'.format(content))

        return response

答案 1 :(得分:8)

Django调试工具栏的中间件实际上有代码,以防止它被激活为非类型的响应,如TastyPie返回的响应。我过去所做的是创建一些中间件,将json响应转换为HTML,这样工具栏就会被激活,我可以计算查询等......这有点像黑客但是它可以完成工作并且很容易打开/关闭。

from django.conf import settings


class JsonAsHTML(object):
    '''
    View a JSON response in your browser as HTML
    Useful for viewing stats using Django Debug Toolbar 

    This middleware should be place AFTER Django Debug Toolbar middleware   
    '''

    def process_response(self, request, response):

        #not for production or production like environment 
        if not settings.DEBUG:
            return response

        #do nothing for actual ajax requests
        if request.is_ajax():
            return response

        #only do something if this is a json response
        if "application/json" in response['Content-Type'].lower():
            title = "JSON as HTML Middleware for: %s" % request.get_full_path()
            response.content = "<html><head><title>%s</title></head><body>%s</body></html>" % (title, response.content)
            response['Content-Type'] = 'text/html'
        return response

答案 2 :(得分:2)

我担心这是不可能的。请参阅已接受的答案以获得可行的解决方案。

这就是为什么你的方法不起作用的原因:

由于答案is not in HTML,工具栏无法启动。工具栏的中间件无法“解析”所有其他格式以包含工具栏。

您可以添加自己的工具来显示SQL查询。看看这个简单的代码段:http://djangosnippets.org/snippets/161/或者您可以使用第三方应用,例如django-snippetscream

例如,您可以检查是否DEBUG is True并将此信息添加到Tastypie返回的“meta”对象中。

另外,请查看控制台(runserver)中的SQL日志记录。一些有用的资源:http://dabapps.com/blog/logging-sql-queries-django-13/

答案 3 :(得分:1)

尝试https://github.com/django-debug-toolbar/django-debug-toolbar/pull/253

pip install git+https://github.com/caktus/django-debug-toolbar@ajax-panel#egg=django-debug-toolbar

这将允许调试工具栏在调用页面上显示有关请求的信息。

或者,如果你想要一个HTML渲染器并且不太喜欢你的项目,我强烈推荐 django-rest-framework

答案 4 :(得分:1)

@html_decorator
def test(request):

    view = resolve("/api/v1/albumimage/like/user/%d/" % 2 )

    accept =  request.META.get("HTTP_ACCEPT")
    accept += ",application/json"
    request.META["HTTP_ACCEPT"] = accept   
    res = view.func(request, **view.kwargs)

    return HttpResponse(res._container)



def html_decorator(func):
    """                                                                                                                                                                                                                                                                       
    wrap it inside html                                                                                                                                                                                                                                                       
    """

    def _decorated(*args, ** kwargs):
        response = func(*args, **kwargs)

        wrapped = ("<html><body>",
                   response.content,
                   "</body></html>")

        return HttpResponse(wrapped)

    return _decorated

这就是我解决它的方法 好吧,这不是自动的,但现在会做。

答案 5 :(得分:1)

我通过从http://djangosnippets.org/snippets/344/

重建django snippest来解决这个问题
"""
Database and request debug info for Tastypie.

Based of idea from http://djangosnippets.org/snippets/344/

# settings.py:
DEBUG=True
DEBUG_SQL=True

MIDDLEWARE_CLASSES = (
    'YOURPATH.SQLLogMiddleware.SQLLogMiddleware',
    'django.middleware.transaction.TransactionMiddleware',
    ...)

"""

# Python
import time
import logging
import json

# Django
from django.conf import settings
from django.db import connection


class SQLLogMiddleware:
    """\
    Attach debug information to result json.
    """
    def process_request(self, request):
        request.sqllog_start = time.time()

    def process_response (self, request, response):
        # request.sqllog_start is empty if an append slash redirect happened.
        debug_sql = getattr(settings, "DEBUG_SQL", False)
        if not getattr(request, 'sqllog_start', False):
            return response
        if (not request.sqllog_start) or not (settings.DEBUG and debug_sql):
            return response

        try:
            content = json.loads(response.content)
        except ValueError:
            return response
        timesql = 0.0
        for query in connection.queries:
            timesql += float(query['time'])
        seen = {}
        duplicate = 0
        for query in connection.queries:
            sql = query["sql"]
            c = seen.get(sql, 0)
            if c:
                duplicate += 1
            if c:
                query["seen"] = c + 1
            seen[sql] = c + 1

        timerequest = round(time.time() - request.sqllog_start, 3)
        queries = connection.queries

        debug = {'request_path': request.path,
                 'query_count': len(queries),
                 'duplicate_query_count': duplicate,
                 'sql_execute_time': timesql,
                 'request_execution_time': timerequest,
                 'queries': []}

        for query in queries:
            debug['queries'].append({'time': query['time'],
                                     'sql': query['sql']})

        content['debug'] = debug
        response.content = json.dumps(content)
        logging.info(debug)
        return response

答案 6 :(得分:1)

Django 1.10推出了&#39;新式中间件&#39;:https://docs.djangoproject.com/en/2.0/releases/1.10/#new-style-middleware

这是一种新的中间件版本:

import json

from django.http import HttpResponse


class NonHtmlDebugToolbarMiddleware:
    """
    The Django Debug Toolbar usually only works for views that return HTML.
    This middleware wraps any non-HTML response in HTML if the request
    has a 'debug' query parameter (e.g. http://localhost/foo?debug)
    Special handling for json (pretty printing) and
    binary data (only show data length)
    """
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        response = self.get_response(request)

        if response['Content-Type'] == 'application/json':
            content = response.content
            try:
                json_ = json.loads(content)
                content = json.dumps(json_, sort_keys=True, indent=2)
            except ValueError:
                pass

            response = HttpResponse('<html><body><pre>{}'
                                    '</pre></body></html>'.format(content),
                                    content_type='text/html')

        return response

答案 7 :(得分:0)

在Django Debug Toolbar的3.1版中,有一个History Panel,不需要用html包装JSON响应。