始终从Django视图返回JSON。
项目描述
django-jsonview 是一个简单的装饰器,它将Python对象转换为JSON,并确保您的视图始终返回JSON。
我经常复制粘贴这个,所以我决定我只是想把它放在一个包里。
安装
只需使用 pip 安装即可
pip install django-jsonview
无需添加到 INSTALLED_APPS 或其他任何内容。
用法
只需导入装饰器,使用,并返回一个可序列化为JSON的对象
from jsonview.decorators import json_view @json_view def my_view(request): return { 'foo': 'bar', }
基于类的视图(CBVs)可以继承自JsonView,使用Django的 @method_decorator 或包装 .as_view() 的输出
# inherit from JsonView from jsonview.views import JsonView class MyView(JsonView): def get_context_data(self, **kwargs): context = super(MyView, self).get_context_data(**kwargs) context['my_key'] = 'some value' return context # or, method decorator from django.utils.decorators import method_decorator from jsonview.decorators import json_view class MyView(View): @method_decorator(json_view) def dispatch(self, *args, **kwargs): return super(MyView, self).dispatch(*args, **kwargs) # or, in URLconf patterns = [ url(r'^/my-view/$', json_view(MyView.as_view())), ]
内容类型
如果您需要返回标准 application/json 之外的内容类型,您可以在装饰器中通过 content_type 参数指定,例如
from jsonview.decorators import json_view @json_view(content_type='application/vnd.github+json') def myview(request): return {'foo': 'bar'}
响应将具有适当的内容类型头。
返回值
默认情况是将您的返回值序列化,并以HTTP 200和内容类型 application/json 进行响应。
@json_view 装饰器将处理许多异常和其他情况,包括
Http404
PermissionDenied
HttpResponseNotAllowed(例如 require_GET,require_POST)
jsonview.exceptions.BadRequest(见下文)
任何其他异常(记录到 django.request)。
这些异常中的任何一个都会返回正确的状态码(例如,404、403、405、400、500),内容类型为 application/json,以及一个看起来像以下内容的响应体:
json.dumps({ 'error': STATUS_CODE, 'message': str(exception), })
BadRequest
HTTP没有针对“你提交了一个未通过验证的表单”这一情况很好的状态码,因此Django对它的支持不是很好。大多数示例只是返回200 OK。
通常,这是没有问题的。但是,如果你通过Ajax提交表单,有一个“OK”和“不行”的区别会很好。HTTP 400 Bad Request响应是用于处理未指定的请求问题的回退,所以让我们这样做。
要使@json_view返回400,只需抛出一个包含任何适当错误消息的jsonview.exceptions.BadRequest。
异常
如果你的视图抛出了异常,@json_view会捕获该异常,将其记录到正常的django.request logger,并返回一个包含状态码500和看起来像返回值部分中的异常的JSON响应。
状态码
如果你需要返回不同的HTTP状态码,只需返回两个值而不是一个。第一个是可序列化的对象,第二个是整数状态码。
@json_view def myview(request): if not request.user.is_subscribed(): # Send a 402 Payment Required status. return {'subscribed': False}, 402 # Send a 200 OK. return {'subscribed': True}
额外头信息
你可以通过返回三个值的元组(一个对象、一个状态码和一个头信息字典)来向响应添加自定义头信息。
@json_view def myview(request): return {}, 200, {'X-Server': 'myserver'}
自定义头信息值可能会被响应中间件覆盖。
原始返回值
为了使将JSON响应作为字符串缓存成为可能(并且因为它们本来就不是JSON可序列化的),如果你返回一个HttpResponse对象(或其子类),它将被不变地传递,例如:
from django import http from jsonview.decorators import JSON @json_view def caching_view(request): kached = cache.get('cache-key') if kached: return http.HttpResponse(kached, content_type=JSON) # Assuming something else populates this cache. return {'complicated': 'object'}
替代JSON实现
现在有一系列健康的JSON解析和生成库。默认情况下,它将使用老牌的stdlib json模块。但是,如果你更愿意使用ujson、cjson或yajl,你可以选择使用它们。只需将此添加到你的Django设置中
JSON_MODULE = 'ujson'
任何,只要它是一个具有.loads()和.dumps()方法的模块。
配置JSON输出
可以通过JSON_OPTIONS = {} Django设置将额外的关键字参数传递给json.dumps()。例如,为了美化打印JSON输出:
JSON_OPTIONS = { 'indent': 4, }
或者为了压缩它:
JSON_OPTIONS = { 'separators': (',', ':'), }
jsonview默认使用DjangoJSONEncoder。要使用不同的JSON编码器,使用cls选项。
JSON_OPTIONS = { 'cls': 'path.to.MyJSONEncoder', }
JSON_OPTIONS['cls']可能是一个点字符串或一个JSONEncoder类。
如果你使用的是一个不支持 `cls` 关键字参数的 JSON 模块,例如 ujson,请将 cls 选项设置为 None
JSON_OPTIONS = { 'cls': None, }
默认的 content-type 是 'application/json'。你可以通过 Django 的 JSON_DEFAULT_CONTENT_TYPE 设置来更改它。例如,要添加字符集
JSON_DEFAULT_CONTENT_TYPE = 'application/json; charset=utf-8'
原子请求
由于 @json_view 会捕获异常,所以正常的 Django 设置 ATOMIC_REQUESTS 并不能正确地触发回滚。可以通过在 @json_view 装饰器 下方 显式设置 @transaction.atomic 来解决这个问题,例如:
@json_view @transaction.atomic def my_func(request): # ...
贡献
测试必须通过,包括你添加的新测试。(见下文。)
覆盖率不应低于 100%。你可以使用 pip 安装 coverage 并运行 ./run.sh coverage 来检查。
flake8 工具不应返回任何问题。
运行测试
要运行测试,你可能需要创建一个 virtualenv,然后使用 pip 安装 Django 和 Mock
pip install Django==${DJANGO_VERSION} mock==1.0.1
然后运行测试:
./run.sh test