Як повернути JSON без використання шаблону в Django?


82

Це пов'язано з цим питанням: Django повертає json і html залежно від клієнтського python


У мене є API командного рядка Python для програми Django. Коли я отримую доступ до програми через API, вона повинна повертати JSON, а з браузером - HTML. Я можу використовувати різні URL-адреси для доступу до різних версій, але як мені відобразити шаблон HTML і JSON у views.py лише одним шаблоном?

Для візуалізації HTML я б використав:

return render_to_response('sample/sample.html....')

Але як би я зробив те саме для JSON, не розміщуючи шаблон JSON? ( content-typeмає бути application/jsonзамість text/html)

Що визначатиме вихід JSON та HTML?

Тож у моєму views.py :

if something:
    return render_to_response('html_template',.....)
else:
    return HttpReponse(jsondata,mimetype='application/json')

@Marcin Ви в основному сказали йому "Ні, не роби так", не показуючи йому приклад правильного шляху. Для цього, здається, призначений ...
Ізката

@ Джиммі, якщо це сталося, ти не повинен був так швидко прийняти відповідь Марсіна на інше питання. Зачекайте принаймні день, хтось, швидше за все, відповів би щось на зразок відповіді Уку Лоскіта
Izkata

@Izkata: Я насправді сказав йому, яку бібліотеку використовувати. Здається, це питання з метою змусити когось іншого написати для нього свій код.
Marcin

Відповіді:


134

Я думаю, що проблема заплуталася щодо того, що ви хочете. Думаю, ви насправді не намагаєтесь вставити HTML у відповідь JSON, а хочете альтернативно повернути HTML або JSON.

По-перше, вам потрібно зрозуміти суть різниці між ними. HTML - це презентаційний формат. Він більше стосується способу відображення даних, ніж самих даних. JSON - це навпаки. Це чисті дані - в основному представлення JavaScript певного набору даних Python (у даному випадку), який у вас є. Він виконує функцію просто обмінного шару, дозволяючи переміщати дані з однієї області програми (подання) в іншу область програми (ваш JavaScript), яка зазвичай не має доступу один до одного.

Маючи це на увазі, ви не "візуалізуєте" JSON, і тут не задіяні шаблони. Ви просто перетворюєте будь-які дані, що відтворюються (швидше за все, те, що ви передаєте як контекст до вашого шаблону), у JSON. Що можна зробити або за допомогою бібліотеки JSON від Django (simplejson), якщо це дані вільної форми, або її серіалізаційну структуру, якщо це набір запитів.

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)

Серіалізація

from django.core import serializers

foos = Foo.objects.all()

data = serializers.serialize('json', foos)

У будь-якому випадку, ви потім передаєте ці дані у відповідь:

return HttpResponse(data, content_type='application/json')

[Редагувати] У Django 1.6 та попередніх версіях код для відповіді був

return HttpResponse(data, mimetype='application/json')

[ РЕДАКТУВАТИ ]: simplejson було видалено з django , ви можете використовувати:

import json

json.dumps({"foo": "bar"})

Або ви можете скористатися django.core.serializersописаним вище способом.


Дякую за роз'яснення. Як я можу визначити у своїх уявленнях, що запит на відповідь надсилається через api для json? Дивіться редагування питання.
Neeran

1
Можна використовувати request.is_ajax(). Але для цього потрібно встановити HTTP_X_REQUESTED_WITHзаголовок. Більшість бібліотек JavaScript роблять це автоматично, але якщо ви використовуєте інший тип клієнта, вам також потрібно переконатися, що він його встановлює. Крім того, ви можете передати рядок запиту, наприклад, ?jsonз URL-адресою, а потім перевірити request.GET.has_key('json'), що, можливо, трохи надійніше.
Кріс Пратт,

18
Зверніть увагу, що зараз simplejson вважається застарілим у Django 1.5 . Використовуйте import json ; json.dumps(data)замість цього.
Йонатан,

1
OP повинен перевірити заголовок узгодження типу вмісту "Прийняти" в requestоб'єкті. Дивіться: w3.org/Protocols/rfc2616/rfc2616-sec14.html (великий мамонт прочитаного, але спрощений зразок коду може бути використаний для демонстрації, і не складно буде скласти негнучку систему, яка б принаймні вирішити дві справи, про які вони просять)
Мерлін Морган-Грем

14
У моєму випадку (Django 1.7) це був content_type = 'application / json', а не mimetype
Nopik


8

У випадку відповіді JSON немає шаблону для відтворення. Шаблони призначені для генерації відповідей HTML. JSON - це відповідь HTTP.

Однак у вас може бути HTML, який відображається із шаблону разом із вашою відповіддю JSON.

html = render_to_string("some.html", some_dictionary)
serialized_data = simplejson.dumps({"html": html})
return HttpResponse(serialized_data, mimetype="application/json")

Чи потрібно спочатку серіалізувати об’єкти?
Neeran

simplejson.dumps () - це те, що робить серіалізація.
Uku Loskit

дякую, це працює абсолютно нормально. ми можемо використовувати json також замість simplejson @UkuLoskit
Chirag Kanzariya

7

Схоже, рамка Django REST використовує заголовок прийняття HTTP у запиті, щоб автоматично визначити, який візуалізатор використовувати:

http://www.django-rest-framework.org/api-guide/renderers/

Використання заголовка HTTP accept може надати альтернативне джерело для вашого "якщо щось".


7

Для візуалізації моїх моделей у JSON у django 1.9 мені потрібно було зробити наступне у своєму view.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')

Ви можете скористатися JsonResponse
MichielB

2

Ви також можете перевірити тип вмісту запиту, як зазначено у RFC. Таким чином, ви можете відтворити HTML за замовчуванням, і там, де ваш клієнт приймає додаток / jason, ви можете повернути json у відповідь без необхідності шаблону


2
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')

1

Ось приклад, який мені потрібен для умовного відтворення json або html залежно від 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)

Ви можете перевірити це за допомогою curl або httpie

$ http localhost:8000/event/
$ http localhost:8000/event/ Accept:application/json

Примітка. Я вирішив не використовувати, JsonReponseоскільки це призведе до повторної серіалізації моделі без потреби.


0

Якщо ви хочете передати результат як відтворений шаблон, вам потрібно завантажити та відтворити шаблон, передайте результат відтворення в json. Це може виглядати так:

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)

Таким чином ви можете передати візуалізований шаблон як json своєму клієнту. Це може бути корисно, якщо ви хочете повністю замінити, тобто. a, що містить безліч різних елементів.


1
Як додаткове зауваження, render_to_stringє ярлик для 3-х рядків "відтворити шаблон" і існує з Django 1.0
Izkata
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.