Esto está relacionado con esta pregunta: Django devuelve json y html según el cliente python
Tengo una API de Python de línea de comandos para una aplicación de Django. Cuando accedo a la aplicación a través de la API, debería devolver JSON y con un navegador debería devolver HTML. Puedo usar diferentes URL para acceder a las diferentes versiones, pero ¿cómo renderizo la plantilla HTML y JSON en views.py con solo una plantilla?
Para renderizar el HTML usaría:
return render_to_response('sample/sample.html....')
Pero, ¿cómo haría lo mismo para JSON sin poner una plantilla JSON? (el content-type
debería ser en application/json
lugar de text/html
)
¿Qué determinaría las salidas JSON y HTML?
Entonces en mi views.py :
if something:
return render_to_response('html_template',.....)
else:
return HttpReponse(jsondata,mimetype='application/json')
python
json
django
django-views
Neeran
fuente
fuente
Respuestas:
Creo que el tema se ha confundido con respecto a lo que quieres. Me imagino que en realidad no está tratando de poner HTML en la respuesta JSON, sino que desea devolver HTML o JSON alternativamente.
Primero, debe comprender la diferencia fundamental entre los dos. HTML es un formato de presentación. Se trata más de cómo mostrar datos que de los datos en sí. JSON es lo contrario. Son datos puros, básicamente una representación de JavaScript de algún conjunto de datos de Python (en este caso) que tiene. Sirve simplemente como una capa de intercambio, lo que le permite mover datos de un área de su aplicación (la vista) a otra área de su aplicación (su JavaScript) que normalmente no tienen acceso entre sí.
Con eso en mente, no "renderiza" JSON y no hay plantillas involucradas. Simplemente convierte cualquier dato que esté en juego (probablemente más o menos lo que está pasando como contexto a su plantilla) a JSON. Lo cual se puede hacer a través de la biblioteca JSON de Django (simplejson), si son datos de forma libre, o su marco de serialización, si es un conjunto de consultas.
simplejson
from django.utils import simplejson some_data_to_dump = { 'some_var_1': 'foo', 'some_var_2': 'bar', } data = simplejson.dumps(some_data_to_dump)
Publicación por entregas
from django.core import serializers foos = Foo.objects.all() data = serializers.serialize('json', foos)
De cualquier manera, luego pasa esos datos a la respuesta:
return HttpResponse(data, content_type='application/json')
[Editar] En Django 1.6 y versiones anteriores, el código para devolver la respuesta era
return HttpResponse(data, mimetype='application/json')
[EDITAR]: simplejson fue eliminado de django , puedes usar:
import json json.dumps({"foo": "bar"})
O puede usar el
django.core.serializers
como se describe arriba.fuente
request.is_ajax()
. Pero eso requiere que elHTTP_X_REQUESTED_WITH
encabezado esté configurado. La mayoría de las bibliotecas de JavaScript hacen esto automáticamente, pero si está utilizando algún otro tipo de cliente, deberá asegurarse de que también lo configure. Alternativamente, puede pasar una cadena de consulta como?json
con la URL y luego verificarrequest.GET.has_key('json')
, que probablemente sea un poco más infalible.import json ; json.dumps(data)
lugar.request
objeto. Ver: w3.org/Protocols/rfc2616/rfc2616-sec14.html (gran parte de una lectura, pero se podría usar una muestra de código simplificado para demostrar, y no sería muy difícil escribir un sistema inflexible que al menos manejar los dos casos que están preguntando)En Django 1.7 esto es aún más fácil con el JsonResponse incorporado.
https://docs.djangoproject.com/en/dev/ref/request-response/#jsonresponse-objects
# import it from django.http import JsonResponse def my_view(request): # do something with the your data data = {} # just return a JsonResponse return JsonResponse(data)
fuente
En el caso de la respuesta JSON, no hay ninguna plantilla para representar. Las plantillas sirven para generar respuestas HTML. El JSON es la respuesta HTTP.
Sin embargo, puede tener HTML que se procesa desde una plantilla dentro de su respuesta JSON.
html = render_to_string("some.html", some_dictionary) serialized_data = simplejson.dumps({"html": html}) return HttpResponse(serialized_data, mimetype="application/json")
fuente
Parece que el marco Django REST usa el encabezado de aceptación HTTP en una Solicitud para determinar automáticamente qué renderizador usar:
http://www.django-rest-framework.org/api-guide/renderers/
El uso del encabezado de aceptación HTTP puede proporcionar una fuente alternativa para su "si algo".
fuente
Para renderizar mis modelos en JSON en django 1.9 tuve que hacer lo siguiente en mi views.py:
from django.core import serializers from django.http import HttpResponse from .models import Mymodel def index(request): objs = Mymodel.objects.all() jsondata = serializers.serialize('json', objs) return HttpResponse(jsondata, content_type='application/json')
fuente
También puede verificar el tipo de contenido de aceptación de solicitud como se especifica en el rfc. De esa manera, puede renderizar por defecto HTML y donde su cliente acepta la aplicación / jason, puede devolver json en su respuesta sin que se requiera una plantilla
fuente
from django.utils import simplejson from django.core import serializers def pagina_json(request): misdatos = misdatos.objects.all() data = serializers.serialize('json', misdatos) return HttpResponse(data, mimetype='application/json')
fuente
Aquí hay un ejemplo que necesitaba para renderizar json o html de forma condicional según el
Accept
encabezado de la solicitud# myapp/views.py from django.core import serializers from django.http import HttpResponse from django.shortcuts import render from .models import Event def event_index(request): event_list = Event.objects.all() if request.META['HTTP_ACCEPT'] == 'application/json': response = serializers.serialize('json', event_list) return HttpResponse(response, content_type='application/json') else: context = {'event_list': event_list} return render(request, 'polls/event_list.html', context)
puedes probar esto con curl o httpie
$ http localhost:8000/event/ $ http localhost:8000/event/ Accept:application/json
tenga en cuenta que opté por no usarlo
JsonReponse
ya que reservaría el modelo innecesariamente.fuente
Si desea pasar el resultado como una plantilla renderizada, debe cargar y renderizar una plantilla, pasar el resultado de renderizarla al json. Esto podría verse así:
from django.template import loader, RequestContext #render the template t=loader.get_template('sample/sample.html') context=RequestContext() html=t.render(context) #create the json result={'html_result':html) json = simplejson.dumps(result) return HttpResponse(json)
De esa manera, puede pasar una plantilla renderizada como json a su cliente. Esto puede ser útil si desea reemplazar completamente ie. que contiene muchos elementos diferentes.
fuente
render_to_string
es un atajo para las 3 líneas "render the template", y existe desde Django 1.0