Как использовать django-debug-toolbar для django-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?
(например, я хотел бы посмотреть, сколько запросов sql выполняется для вызовов api.. и т.д.)
Может быть, я могу вызвать api из представлений django, но как?
Ответы
Ответ 1
Вот промежуточное программное обеспечение, которое я написал для аналогичных целей, которое обертывает json в HTML для включения панели инструментов отладки, а также довольно печатает ее. Кроме того, он поддерживает двоичные данные. Я не использую 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
Ответ 2
В промежуточном программном пакете Django Debug на самом деле есть код, чтобы он не активировался для ответов типа non-html, таких как те, которые возвращались 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
Ответ 3
Я боюсь, что это невозможно. См. принятый ответ для работоспособного решения.
Вот почему ваш подход не сработал:
Панель инструментов не срабатывает, потому что ответ отсутствует в HTML. Все другие форматы не могут быть "проанализированы" промежуточным программным обеспечением панели инструментов, чтобы включить панель инструментов.
Вы можете добавить свои собственные инструменты, чтобы показывать SQL-запросы. Взгляните на этот простой фрагмент: http://djangosnippets.org/snippets/161/ Или вы можете использовать стороннее приложение для этого, например django-snippetscream.
Например, вы можете проверить, есть ли DEBUG is True
и добавить эту информацию в объект "meta", возвращенный Tastypie.
Кроме того, взгляните на ведение журнала SQL в консоли (servererver). Некоторый полезный ресурс для этого: http://dabapps.com/blog/logging-sql-queries-django-13/
Ответ 4
Попробуйте https://github.com/django-debug-toolbar/django-debug-toolbar/pull/253
pip install git+https://github.com/caktus/[email protected]#egg=django-debug-toolbar
Это позволит панели инструментов отладки отображать информацию о запросе на вызывающей странице.
В качестве альтернативы, если вы хотите, чтобы средство визуализации HTML и ваш не слишком далеко от вашего проекта, я настоятельно рекомендую django-rest-framework
Ответ 5
@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
Вот как я это решил.
Хорошо, это не автоматическое, но сейчас все будет сделано.
Ответ 6
Я исправил это, восстановив django snippest из http://djangosnippets.org/snippets/344/
"""
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