framework - ¿Cómo usar django-debug-toolbar para django-tastypie?
tastypie github (7)
django-debug-toolbar necesita que su salida sea html, pero el formato de salida predeterminado de django-tastypie es json.
Intenté enviar http://localhost/api/v1/resource/?format=html
pero dice: Sorry, not implemented yet. Please append "?format=json" to your URL
Sorry, not implemented yet. Please append "?format=json" to your URL
Aunque este documento enumera html como una opción válida, dice que está en la TODO list
.
http://django-tastypie.readthedocs.org/en/latest/serialization.html#to-html
¿Cómo uso la barra de herramientas de depuración para depurar las llamadas de la API de tastypie?
(por ejemplo, me gustaría ver cuántas consultas de SQL se están ejecutando para las llamadas a la API ... y así sucesivamente)
Tal vez pueda llamar a la api desde las vistas de django pero ¿cómo?
Aquí hay un middleware que escribí para propósitos similares que envuelve a json en HTML para habilitar la barra de herramientas de depuración y también la imprime. Además, soporta datos binarios. No estoy usando tastypie, pero creo que debería funcionar con eso también.
# 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.10 introdujo el ''nuevo estilo de middleware'': https://docs.djangoproject.com/en/2.0/releases/1.10/#new-style-middleware
Esta es una nueva versión de middleware de estilo:
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
El middleware de la barra de herramientas de depuración de Django en realidad tiene un código para evitar que se active para respuestas de tipo no html como las devueltas por TastyPie. Lo que he hecho en el pasado es crear un poco de middleware que convierte las respuestas de json en HTML para que la barra de herramientas se active y pueda contar las consultas, etc. Es un poco difícil, pero hace un buen trabajo y es fácil para encender / apagar.
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
Lo arreglé reconstruyendo django snippest desde 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
Pruebe 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
Esto permitirá que la barra de herramientas de depuración muestre información sobre la solicitud en la página de llamada.
Alternativamente, si desea un renderizador HTML y no está demasiado lejos en su proyecto, le recomiendo django-rest-framework
Me temo que eso no es posible. Vea la respuesta aceptada para una solución viable.
Aquí es por qué su enfoque no funcionó:
La barra de herramientas no se activa porque la respuesta no está en HTML . Todos los demás formatos no pueden ser "analizados" por el middleware de la barra de herramientas para incluir la barra de herramientas.
Sin embargo, puede agregar sus propias herramientas para mostrar consultas SQL. Eche un vistazo a este simple fragmento de código: http://djangosnippets.org/snippets/161/ O puede usar una aplicación de terceros para esto, como django-snippetscream .
Por ejemplo, puede verificar si DEBUG is True
y agregar esta información al objeto "meta" devuelto por Tastypie.
Además, eche un vistazo al registro de SQL en su consola (runserver). Algunos recursos útiles para esto: http://dabapps.com/blog/logging-sql-queries-django-13/
@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
Así lo resolví.
Ok, no es automático, pero lo hará por ahora.