【问题标题】:How to use django-debug-toolbar for django-tastypie?如何为 django-tastypie 使用 django-debug-toolbar?
【发布时间】:2013-01-15 02:34:03
【问题描述】:

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,但是如何调用?

【问题讨论】:

    标签: django debugging tastypie


    【解决方案1】:

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

    【讨论】:

      【解决方案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
      

      【讨论】:

      • 谢谢。虽然评论不正确,但没有检查查询参数:}
      【解决方案3】:

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

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

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

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

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

      此外,请查看控制台 (runserver) 中的 SQL 日志记录。一些有用的资源:@​​987654324@

      【讨论】:

        【解决方案4】:

        我通过从 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
        

        【讨论】:

        • django.middleware.transaction.TransactionMiddleware 在 Django 1.6 中已弃用。如果没有它,则不会将调试信息添加到响应中。
        【解决方案5】:

        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
        

        【讨论】:

          【解决方案6】:

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

          # 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
          

          【讨论】:

          • 次要修复:对于 Django 1.7 的回答,这对我不起作用。我必须更改 MIDDLEWARE_CLASSES 包括:我必须指定“myapp.settings.NonHtmlDebugToolbarMiddleware”而不是“NonHtmlDebugToolbarMiddleware”。除此之外 - 太棒了!
          • @karan 它与 django rest API 完美配合,但是当我将它与 swagger 一起使用时,它在 sql 面板中显示 0 个查询,即使我运行了一些查询。你能推荐一些东西吗?
          • 这将破坏当前版本 django-debug-toolbar 上的工具栏面板,因为它会尝试将来自其自身端点的响应解析为 JSON。我对此进行了修改,以允许 'application/json' 响应在不修改的情况下通过,以便它在当前包版本上工作。
          【解决方案7】:
          @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
          

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

          【讨论】:

            【解决方案8】:

            试试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

            【讨论】:

              猜你喜欢
              • 2016-04-08
              • 2011-07-04
              • 2021-07-15
              • 2022-08-13
              • 2014-08-28
              • 2015-03-22
              • 2011-08-05
              • 2012-05-18
              • 1970-01-01
              相关资源
              最近更新 更多