Làm cách nào để trả lại JSON mà không sử dụng mẫu trong Django?


81

Điều này liên quan đến câu hỏi này: Django trả về json và html tùy thuộc vào ứng dụng khách python


Tôi có một API Python dòng lệnh cho ứng dụng Django. Khi tôi truy cập ứng dụng thông qua API, nó sẽ trả về JSON và với trình duyệt, nó sẽ trả về HTML. Tôi có thể sử dụng các URL khác nhau để truy cập các phiên bản khác nhau nhưng làm cách nào để hiển thị mẫu HTML và JSON trong views.py chỉ với một mẫu?

Để hiển thị HTML, tôi sẽ sử dụng:

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

Nhưng làm cách nào để làm điều tương tự với JSON mà không cần đặt mẫu JSON? ( content-typenên được application/jsonthay vì text/html)

Điều gì sẽ xác định kết quả đầu ra JSON và HTML?

Vì vậy, trong views.py :

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

@Marcin Về cơ bản, bạn đã nói với anh ấy "Không, đừng làm theo cách này" mà không chỉ cho anh ấy một ví dụ về cách làm đúng. Đó là những gì cái này dường như dành cho ...
Izkata

@Jimmy, nếu đó là những gì đã xảy ra, bạn không nên chấp nhận câu trả lời của Marcin cho câu hỏi khác nhanh như vậy. Chờ ít nhất một ngày, ai đó có thể sẽ trả lời với một cái gì đó giống như câu trả lời của Uku Loskit
Izkata

@Izkata: Tôi thực sự đã nói cho anh ấy biết nên sử dụng thư viện nào. Câu hỏi này dường như nhằm mục đích nhờ người khác viết mã cho anh ta.
Marcin

Câu trả lời:


131

Tôi nghĩ rằng vấn đề đã trở nên bối rối liên quan đến những gì bạn muốn. Tôi tưởng tượng rằng bạn không thực sự cố gắng đưa HTML vào phản hồi JSON, mà muốn trả về HTML hoặc JSON theo cách khác.

Trước tiên, bạn cần hiểu sự khác biệt cốt lõi giữa hai loại. HTML là một định dạng trình bày. Nó đề cập nhiều đến cách hiển thị dữ liệu hơn là chính dữ liệu. JSON thì ngược lại. Đó là dữ liệu thuần túy - về cơ bản là biểu diễn JavaScript của một số tập dữ liệu Python (trong trường hợp này) mà bạn có. Nó chỉ đóng vai trò như một lớp trao đổi, cho phép bạn di chuyển dữ liệu từ một khu vực của ứng dụng (chế độ xem) sang một khu vực khác của ứng dụng (JavaScript của bạn) mà thông thường không có quyền truy cập vào nhau.

Với ý nghĩ đó, bạn không "kết xuất" JSON và không có mẫu nào liên quan. Bạn chỉ đơn thuần chuyển đổi bất kỳ dữ liệu nào đang phát (rất có thể là những gì bạn đang chuyển làm bối cảnh cho mẫu của mình) sang JSON. Điều này có thể được thực hiện thông qua thư viện JSON của Django (simplejson), nếu đó là dữ liệu dạng tự do hoặc khuôn khổ tuần tự hóa của nó, nếu đó là bộ truy vấn.

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)

Serialization

from django.core import serializers

foos = Foo.objects.all()

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

Dù bằng cách nào, bạn sau đó chuyển dữ liệu đó vào phản hồi:

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

[Chỉnh sửa] Trong Django 1.6 trở về trước, mã để trả lại phản hồi là

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

[EDIT]: simplejson đã bị xóa khỏi django , bạn có thể sử dụng:

import json

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

Hoặc bạn có thể sử dụng django.core.serializersnhư mô tả ở trên.


Cảm ơn bạn đã làm rõ. Làm cách nào để xác định trong quan điểm của tôi rằng yêu cầu phản hồi là của api cho json? Xem chỉnh sửa trên câu hỏi.
Neeran

1
Bạn có thể sử dụng request.is_ajax(). Nhưng điều đó yêu cầu rằng HTTP_X_REQUESTED_WITHtiêu đề phải được thiết lập. Hầu hết các thư viện JavaScript thực hiện điều này một cách tự động, nhưng nếu bạn đang sử dụng một số loại ứng dụng khách khác, bạn sẽ cần đảm bảo rằng nó cũng đặt nó. Ngoài ra, bạn có thể chuyển một chuỗi truy vấn chẳng hạn như ?jsonvới URL và sau đó kiểm tra request.GET.has_key('json'), điều này có thể dễ dàng hơn một chút.
Chris Pratt

18
Lưu ý rằng simplejson hiện không được dùng bởi Django 1.5 . Sử dụng import json ; json.dumps(data)thay thế.
Yonatan

1
OP nên kiểm tra tiêu đề thương lượng loại nội dung "Chấp nhận" trong requestđối tượng. Hãy xem: w3.org/Protocols/rfc2616/rfc2616-sec14.html (đọc rất nhiều, nhưng một mẫu mã đơn giản có thể được sử dụng để chứng minh và sẽ không quá khó để viết một hệ thống không linh hoạt mà ít nhất là xử lý hai trường hợp họ đang yêu cầu)
Merlyn Morgan-Graham

14
Trong trường hợp của tôi (Django 1.7), đó là content_type = 'application / json', không phải mimetype
Nopik 13/1014


8

Trong trường hợp của phản hồi JSON, không có mẫu nào được hiển thị. Các mẫu là để tạo phản hồi HTML. JSON là phản hồi HTTP.

Tuy nhiên, bạn có thể có HTML được hiển thị từ một mẫu chứa phản hồi JSON của bạn.

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

Tôi có phải tuần tự hóa các đối tượng trước không?
Neeran

simplejson.dumps () là quá trình tuần tự hóa.
Uku Loskit

cảm ơn bạn nó hoạt động hoàn toàn tốt. chúng ta có thể sử dụng json cũng thay vì @UkuLoskit simplejson
Chirag Kanzariya


7

Để hiển thị các mô hình của tôi trong JSON trong django 1.9, tôi phải thực hiện như sau trong 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')

Bạn có thể sử dụng JsonResponse
MichielB 11/09/19

2

Bạn cũng có thể kiểm tra loại nội dung chấp nhận yêu cầu như được chỉ định trong rfc. Bằng cách đó, bạn có thể hiển thị theo HTML mặc định và khi khách hàng của bạn chấp nhận ứng dụng / jason, bạn có thể trả lại json trong phản hồi của mình mà không cần mẫu


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

Đây là một ví dụ tôi cần để hiển thị có điều kiện json hoặc html tùy thuộc vào Accepttiêu đề của Yêu cầu

# 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)

bạn có thể kiểm tra điều này bằng curl hoặc httpie

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

lưu ý rằng tôi đã chọn không sử dụng JsonReponsevì điều đó sẽ thiết lập lại mô hình một cách không cần thiết.


0

Nếu bạn muốn chuyển kết quả dưới dạng một mẫu được hiển thị, bạn phải tải và hiển thị một mẫu, hãy chuyển kết quả của việc hiển thị nó cho json. Điều này có thể trông giống như sau:

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)

Bằng cách đó, bạn có thể chuyển một mẫu được kết xuất dưới dạng json cho khách hàng của mình. Điều này có thể hữu ích nếu bạn muốn thay thế hoàn toàn tức là. a chứa nhiều phần tử khác nhau.


1
Như một lưu ý phụ, render_to_stringlà một phím tắt cho 3 dòng "hiển thị mẫu" và đã tồn tại kể từ Django 1.0
Izkata
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.