使用 Django TastyPie,当我向仅接受 JSON 的 API 发出非 JSON 请求时,我收到 500 错误和包含此回溯的响应:
Traceback (most recent call last):
File ".../lib/python3.3/site-packages/tastypie/resources.py", line 195, in wrapper
response = callback(request, *args, **kwargs)
File ".../lib/python3.3/site-packages/tastypie/resources.py", line 426, in dispatch_list
return self.dispatch('list', request, **kwargs)
File ".../lib/python3.3/site-packages/tastypie/resources.py", line 458, in dispatch
response = method(request, **kwargs)
File ".../lib/python3.3/site-packages/tastypie/resources.py", line 1317, in post_list
deserialized = self.deserialize(request, request.body, format=request.META.get('CONTENT_TYPE', 'application/json'))
File ".../lib/python3.3/site-packages/tastypie/resources.py", line 375, in deserialize
deserialized = self._meta.serializer.deserialize(data, format=request.META.get('CONTENT_TYPE', 'application/json'))
File ".../lib/python3.3/site-packages/tastypie/serializers.py", line 219, in deserialize
raise UnsupportedFormat("The format indicated '%s' had no available deserialization method. Please check your ``formats`` and ``content_types`` on your Serializer." % format)
tastypie.exceptions.UnsupportedFormat: The format indicated 'application/x-www-form-urlencoded' had no available deserialization method. Please check your ``formats`` and ``content_types`` on your Serializer.
我无意添加对表单数据的支持,因此与 400(错误请求)或 415(不支持的媒体类型)相比,500(内部服务器错误)似乎不合适。但我似乎无法弄清楚你应该如何指定 TastyPie 返回这些代码。这是我尚未发现的 TastyPie 功能,还是我必须手动启用此功能?
最佳答案
第 1 部分 - 序列化
您可以创建带有额外反序列化的父资源:
class ExtraPostResource(object):
def deserialize(self, request, data, format=None):
"""
Changes request stat in to python objects
"""
if not format:
format = request.META.get('CONTENT_TYPE', 'application/json')
if format == 'application/x-www-form-urlencoded':
return request.POST
if format.startswith('multipart'):
multipart_data = request.POST.copy()
multipart_data.update(request.FILES)
return multipart_data
return super(ExtraPostResource, self).deserialize(request, data, format)
然后把它应用到你需要的资源上:
class MyModel(ExtraPostResource, ModelResource):
class Meta:
serializer = Serializer(formats=['json'])
queryset = MyModel.objects.all()
resource_name = 'my_model'
我没有用 application/x-www-form-urlencoded
测试这个例子,但是 multipart
对我来说很完美。
现在是第 2 部分 - 大约 500 秒
如果你想处理 500s。
try:
from django.views.decorators.csrf import csrf_exempt
except ImportError:
def csrf_exempt(func):
return func
class MyBaseModelResource(ModelResource):
"""
Basically it defines own error feedback format.
"""
def wrap_view(self, view):
"""
Wraps views to return custom error codes instead of generic 500's.
"""
@csrf_exempt
def wrapper(request, *args, **kwargs): # * see annotation below.
try:
callback = getattr(self, view)
response = callback(request, *args, **kwargs)
if request.is_ajax():
patch_cache_control(response, no_cache=True)
return response
# You can handle here many more.
# [...]
except UnsupportedFormat, e:
return self.create_response(
request,
{'success': False,
'code': 123,
'message': e},
response_class=HttpBadRequest, # HttpForbidden, HttpUnauthorized etc.
)
except Exception, e:
# Rather than re-raising, we're going to things similar to
# what Django does. The difference is returning a serialized
# error message.
return self._handle_500(request, e)
return wrapper
*(1) 值得一提的是,包装方法的版本可能与您当前使用的 Tastypie 版本略有或很多不同。您必须检查它。
关于python - Django TastyPie : how do I return something other than 500 for UnsupportedFormat?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21608106/