Djangoでテンプレートを使用せずにJSONを返すにはどうすればよいですか?


81

これはこの質問に関連しています:DjangoはクライアントのPythonに応じてjsonとhtmlを返します


Djangoアプリ用のコマンドラインPythonAPIがあります。APIを介してアプリにアクセスすると、JSONが返され、ブラウザーではHTMLが返されます。さまざまなURLを使用してさまざまなバージョンにアクセスできますが、1つのテンプレートだけでviews.pyにHTMLテンプレートとJSONをレンダリングするにはどうすればよいですか?

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あなたは基本的に彼に正しい方法の例を示さずに「いいえ、このようにしないでください」と言いました。...この1つはのためにあると思われる何が
Izkata

@ジミー、もしそれが起こったのなら、あなたは他の質問に対するマーシンの答えをそれほど早く受け入れるべきではなかった。少なくとも1日待ってください、誰かがUku Loskitの答えのようなもので答えたでしょう
Izkata 2012

@Izkata:実際にどのライブラリを使用するかを彼に伝えました。この質問は、他の誰かに彼のために彼のコードを書かせることを目的としているようです。
Marcin 2012

回答:


131

問題はあなたが何を望んでいるかに関して混乱していると思います。実際にHTMLをJSON応答に入れようとしているのではなく、代わりにHTMLまたはJSONのいずれかを返したいと思います。

まず、2つのコアの違いを理解する必要があります。HTMLは表示形式です。データ自体よりもデータの表示方法を扱います。JSONはその反対です。それは純粋なデータです-基本的にあなたが持っているいくつかのPython(この場合)データセットのJavaScript表現です。これは単なる交換レイヤーとして機能し、アプリのある領域(ビュー)から、通常は相互にアクセスできないアプリの別の領域(JavaScript)にデータを移動できるようにします。

このことを念頭に置いて、JSONを「レンダリング」することはなく、テンプレートも必要ありません。実行中のデータ(ほとんどの場合、コンテキストとしてテンプレートに渡すもの)をJSONに変換するだけです。これは、自由形式のデータの場合はDjangoのJSONライブラリ(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上記のように使用できます。


ご説明ありがとうございます。私の見解では、応答要求がjsonのAPIによるものであるとどのように判断しますか?質問の編集を参照してください。
ニーラン2012

1
を使用できますrequest.is_ajax()。ただし、HTTP_X_REQUESTED_WITHヘッダーが設定されている必要があります。ほとんどのJavaScriptライブラリはこれを自動的に実行しますが、他のタイプのクライアントを使用している場合は、それも設定されていることを確認する必要があります。または、?jsonURLなどのクエリ文字列を渡してからチェックすることもできますrequest.GET.has_key('json')。これはおそらくもう少し確実です。
クリスプラット

18
simplejsonは、Django1.5では非推奨と見なさていることに注意してください。import json ; json.dumps(data)代わりに使用してください。
ヨナタン2013

1
OPは、requestオブジェクトの「Accept」コンテンツタイプネゴシエーションヘッダーをチェックする必要があります。参照:w3.org/Protocols/rfc2616/rfc2616-sec14.html(読み取りの大きなマンモスですが、簡略化されたコードサンプルを使用してデモンストレーションを行うことができ、少なくとも柔軟性のないシステムを作成することはそれほど難しくありません。彼らが求めている2つのケースを処理します)
Merlyn Morgan-Graham

14
私の場合(Django 1.7)は、mimetypeではなくcontent_type = 'application / json'でした
Nopik 2014年


8

JSON応答の場合、レンダリングするテンプレートはありません。テンプレートは、HTML応答を生成するためのものです。JSONはHTTP応答です。

ただし、JSON応答を使用してテンプレートからレンダリングされるHTMLを使用できます。

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

最初にオブジェクトをシリアル化する必要がありますか?
Neeran 2012

simplejson.dumps()は、シリアル化を行うものです。
Uku Loskit 2012

本当にうまく機能していただきありがとうございます。我々は代わりのsimplejson @UkuLoskitのもJSONを使用することができます
チラグKanzariya


7

django 1.9でモデルをJSONでレンダリングするには、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')

あなたは使用することができますJsonResponse
MichielB

2

rfcで指定されているように、Request Accept ContentTypeを確認することもできます。そうすれば、デフォルトでHTMLをレンダリングでき、クライアントがアプリケーション/ジェイソンを受け入れる場合、テンプレートを必要とせずに応答で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

リクエストのAcceptヘッダーに応じてjsonまたはhtmlを条件付きでレンダリングするために必要な例を次に示します。

# 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としてクライアントに渡すことができます。これは、ieを完全に置き換えたい場合に役立ちます。たくさんの異なる要素が含まれています。


1
補足として、これrender_to_stringは3つの「テンプレートをレンダリングする」行のショートカットであり、Django 1.0
Izkata 2012
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.