Ceci est lié à cette question: Django retourne json et html en fonction du client python
J'ai une ligne de commande Python API pour une Django. Lorsque j'accède à l'application via l'API, elle doit renvoyer JSON et avec un navigateur, elle doit renvoyer HTML Je peux utiliser différentes URL pour accéder aux différentes versions, mais comment puis-je restituer le modèle HTML et le code JSON dans le views.py avec un seul modèle?
Pour rendre le code HTML, j'utiliserais:
return render_to_response('sample/sample.html....')
Mais comment ferais-je la même chose pour JSON sans mettre un modèle JSON? (le content-type
devrait être application/json
au lieu de text/html
)
Que détermineraient les sorties JSON et HTML?
Donc dans my views.py :
if something:
return render_to_response('html_template',.....)
else:
return HttpReponse(jsondata,mimetype='application/json')
Je pense que la question est devenue confuse quant à ce que vous voulez. J'imagine que vous n'essayez pas réellement de placer le code HTML dans la réponse JSON, mais plutôt de renvoyer le code HTML ou le code JSON.
Premièrement, vous devez comprendre la différence fondamentale entre les deux. HTML est un format de présentation. Il traite plus de la façon d'afficher les données que les données elles-mêmes. JSON est le contraire. Il s’agit de données pures - il s’agit essentiellement d’une représentation JavaScript de certains de vos ensembles de données Python (dans ce cas). Elles servent simplement de couche d’échange, ce qui vous permet de déplacer les données d’une zone de votre application ( la vue) vers une autre zone de votre application (votre JavaScript) qui n’a normalement pas accès les uns aux autres.
En gardant cela à l'esprit, vous ne "rendez" pas JSON, et aucun modèle n'est impliqué. Vous convertissez simplement les données en jeu (très probablement ce que vous transmettez comme contexte à votre modèle) en JSON. Ce qui peut être fait via la bibliothèque JSON de Django (simplejson), s’il s’agit de données freeform, ou son framework de sérialisation, s’il s’agit d’un queryset.
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)
Sérialisation
from Django.core import serializers
foos = Foo.objects.all()
data = serializers.serialize('json', foos)
Quoi qu'il en soit, vous transmettez ensuite ces données à la réponse:
return HttpResponse(data, content_type='application/json')
[Edit] Dans Django 1.6 et versions antérieures, le code pour renvoyer la réponse était
return HttpResponse(data, mimetype='application/json')
Dans Django 1.7, cela est encore plus facile avec JsonResponse intégré.
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)
Dans le cas de la réponse JSON, aucun modèle ne doit être rendu. Les modèles servent à générer des réponses HTML. Le JSON est la réponse HTTP.
Cependant, vous pouvez obtenir du code HTML rendu à partir d'un modèle avec votre réponse JSON.
html = render_to_string("some.html", some_dictionary)
serialized_data = simplejson.dumps({"html": html})
return HttpResponse(serialized_data, mimetype="application/json")
Il semble que le framework Django REST utilise l'en-tête HTTP accept dans une requête afin de déterminer automatiquement le rendu à utiliser:
http://www.Django-rest-framework.org/api-guide/renderers/
L'utilisation de l'en-tête HTTP accept peut fournir une source alternative pour votre "si quelque chose".
Pour rendre mes modèles au format JSON dans Django 1.9, je devais effectuer les opérations suivantes dans mon 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')
Vous pouvez également vérifier que le type de contenu accepté par la demande est spécifié dans la RFC. De cette façon, vous pouvez générer un rendu HTML par défaut et, lorsque votre client accepte application/jason, vous pouvez renvoyer json dans votre réponse sans qu'un modèle ne soit nécessaire.
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')
Voici un exemple dont j'avais besoin pour le rendu conditionnel de json ou de html en fonction de l'en-tête de la demande Accept
# 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)
vous pouvez le tester avec curl ou httpie
$ http localhost:8000/event/
$ http localhost:8000/event/ Accept:application/json
note J'ai choisi de ne pas utiliser JsonReponse
comme cela le ferait resérialiser le modèle inutilement.
Si vous voulez transmettre le résultat en tant que modèle de rendu, vous devez charger et rendre un modèle, transmettez le résultat du rendu au json. Cela pourrait ressembler à cela:
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 cette façon, vous pouvez transmettre un modèle de rendu en json à votre client. Cela peut être utile si vous voulez remplacer complètement ie. un contenant beaucoup d'éléments différents.