25

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

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

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

4

8 回答 8

39

这是我为类似目的编写的一个中间件,它将 json 包装在 HTML 中以启用调试工具栏并漂亮地打印它。此外,它支持二进制数据。我没有使用美味的派,但我认为它也应该适用。

# 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
于 2013-10-08T13:49:55.580 回答
8

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

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
于 2013-11-04T21:59:01.157 回答
2

恐怕这是不可能的。请参阅已接受的答案以获取可行的解决方案。

这就是您的方法不起作用的原因:

工具栏没有启动,因为答案不在 HTML 中。工具栏的中间件不能“解析”所有其他格式以包含工具栏。

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

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

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

于 2013-01-31T04:57:46.770 回答
2

Django 1.10 引入了“新型中间件”: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
于 2018-04-25T14:01:59.993 回答
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

于 2013-01-31T05:08:54.600 回答
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

这就是我解决它的方法。
好的,这不是自动的,但现在可以了。

于 2013-02-01T13:59:08.467 回答
1

我通过从http://djangosnippets.org/snippets/344/重建 django 片段来解决这个问题

"""
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
于 2013-09-18T15:34:41.577 回答
0

使用 3.1 版的 Django 调试工具栏,有一个历史面板,它消除了使用 html 包装 JSON 响应的需要。

于 2020-12-14T17:43:43.950 回答