Jest to związane z tym pytaniem: Django zwraca json i html w zależności od klienta Python
Mam interfejs API Pythona z wiersza poleceń dla aplikacji Django. Kiedy uzyskuję dostęp do aplikacji przez API, powinna ona zwrócić JSON, a przy przeglądarce powinien zwrócić HTML. Mogę używać różnych adresów URL, aby uzyskać dostęp do różnych wersji, ale jak renderować szablon HTML i JSON w views.py za pomocą tylko jednego szablonu?
Aby renderować HTML, użyłbym:
return render_to_response('sample/sample.html....')
Ale jak zrobiłbym to samo dla JSON bez umieszczania szablonu JSON? ( content-type
powinno być application/json
zamiast text/html
)
Co określiłoby dane wyjściowe JSON i HTML?
Więc w moim views.py :
if something:
return render_to_response('html_template',.....)
else:
return HttpReponse(jsondata,mimetype='application/json')
python
json
django
django-views
Neeran
źródło
źródło
Odpowiedzi:
Myślę, że problem stał się niejasny, jeśli chodzi o to, czego chcesz. Wyobrażam sobie, że tak naprawdę nie próbujesz umieścić kodu HTML w odpowiedzi JSON, ale raczej chcesz alternatywnie zwrócić HTML lub JSON.
Po pierwsze, musisz zrozumieć podstawową różnicę między nimi. HTML to format prezentacyjny. Zajmuje się bardziej sposobem wyświetlania danych niż samymi danymi. JSON jest odwrotny. To czyste dane - w zasadzie reprezentacja JavaScript jakiegoś zbioru danych Pythona (w tym przypadku), który posiadasz. Służy jedynie jako warstwa wymiany, umożliwiając przenoszenie danych z jednego obszaru aplikacji (widoku) do innego obszaru aplikacji (JavaScript), które zwykle nie mają do siebie dostępu.
Mając to na uwadze, nie „renderujesz” JSON i nie ma tam żadnych szablonów. Po prostu konwertujesz wszystkie dane w grze (najprawdopodobniej prawie to, co przekazujesz jako kontekst do swojego szablonu) na JSON. Można to zrobić za pomocą biblioteki JSON Django (simplejson), jeśli są to dane w dowolnym formacie, lub jego struktury serializacji, jeśli jest to zestaw zapytań.
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)
Serializacja
from django.core import serializers foos = Foo.objects.all() data = serializers.serialize('json', foos)
Tak czy inaczej, następnie przekazujesz te dane do odpowiedzi:
return HttpResponse(data, content_type='application/json')
[Edytuj] W Django 1.6 i wcześniejszych kod zwracał odpowiedź
return HttpResponse(data, mimetype='application/json')
[EDYCJA]: simplejson została usunięta z django , możesz użyć:
import json json.dumps({"foo": "bar"})
Lub możesz użyć,
django.core.serializers
jak opisano powyżej.źródło
request.is_ajax()
. Ale to wymaga ustawieniaHTTP_X_REQUESTED_WITH
nagłówka. Większość bibliotek JavaScript robi to automatycznie, ale jeśli używasz innego typu klienta, musisz się upewnić, że on również go ustawia. Alternatywnie możesz przekazać kwerendę, na przykład za?json
pomocą adresu URL, a następnie sprawdzićrequest.GET.has_key('json')
, co jest prawdopodobnie bardziej niezawodne.import json ; json.dumps(data)
zamiast tego.request
obiekcie. Zobacz: w3.org/Protocols/rfc2616/rfc2616-sec14.html (wielka mamuta do przeczytania, ale do zademonstrowania można użyć uproszczonego kodu, a nie byłoby trudno napisać nieelastyczny system, który przynajmniej załatwić dwie sprawy, o które pytają)W Django 1.7 jest to jeszcze łatwiejsze dzięki wbudowanemu JsonResponse.
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)
źródło
W przypadku odpowiedzi JSON nie ma szablonu do renderowania. Szablony służą do generowania odpowiedzi HTML. JSON to odpowiedź HTTP.
Możesz jednak mieć kod HTML, który jest renderowany z szablonu z odpowiedzią JSON.
html = render_to_string("some.html", some_dictionary) serialized_data = simplejson.dumps({"html": html}) return HttpResponse(serialized_data, mimetype="application/json")
źródło
Wygląda na to, że framework Django REST używa nagłówka HTTP accept w żądaniu, aby automatycznie określić, którego renderera użyć:
http://www.django-rest-framework.org/api-guide/renderers/
Użycie nagłówka akceptacji HTTP może zapewnić alternatywne źródło dla twojego „jeśli coś”.
źródło
Aby renderować moje modele w JSON w django 1.9, musiałem wykonać następujące czynności w moim 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')
źródło
Możesz również sprawdzić żądanie akceptowania typu zawartości, jak określono w rfc. W ten sposób możesz renderować domyślnie HTML i tam, gdzie twój klient akceptuje application / jason, możesz zwrócić json w swojej odpowiedzi bez wymaganego szablonu
źródło
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')
źródło
Oto przykład, którego potrzebowałem do warunkowego renderowania json lub html w zależności od
Accept
nagłówka żądania# 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)
możesz to sprawdzić za pomocą curl lub httpie
$ http localhost:8000/event/ $ http localhost:8000/event/ Accept:application/json
uwaga: zdecydowałem się nie używać,
JsonReponse
ponieważ spowodowałoby to niepotrzebną reserializację modelu .źródło
Jeśli chcesz przekazać wynik jako wyrenderowany szablon, musisz załadować i wyrenderować szablon, przekaż wynik renderowania go do json.Może to wyglądać tak:
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)
W ten sposób możesz przekazać klientowi renderowany szablon jako json. Może to być przydatne, jeśli chcesz całkowicie zastąpić np. a zawierający wiele różnych elementów.
źródło
render_to_string
jest to skrót do 3 linii "renderuj szablon", który istnieje od Django 1.0