如何在Django中不使用模板返回JSON?

93 投票
10 回答
136991 浏览
提问于 2025-04-17 12:57

这段内容跟这个问题有关:Django根据客户端返回JSON和HTML


我有一个命令行的Python API,用于一个Django应用。当我通过API访问这个应用时,它应该返回JSON格式的数据,而通过浏览器访问时,它应该返回HTML格式的页面。我可以用不同的URL来访问这两种版本,但我该如何在views.py中用同一个模板来渲染HTML和JSON呢?

要渲染HTML,我会这样做:

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

但是我该如何在不使用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')

10 个回答

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")
133

在Django 1.7中,使用内置的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)
145

我觉得大家对你想要的东西有点搞混了。我想你其实不是想把HTML放进JSON的响应里,而是想要根据需要返回HTML或者JSON。

首先,你需要明白这两者的核心区别。HTML是一种展示格式,它主要关注的是如何显示数据,而不是数据本身。JSON则正好相反,它是纯数据——基本上是你在Python中使用的数据集的一种JavaScript表示。JSON只是一个数据交换的工具,让你可以在应用的不同部分(比如视图和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,如上所述。

撰写回答