使用Django TastyPie,当我向只接受JSON的API提供非JSON请求时,我收到500错误和包含此回溯的repsonse:
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.
我无意添加对formdata的支持,因此与400(错误请求)或415(不支持的媒体类型)相比,500(内部服务器错误)似乎不合适。但我似乎无法弄清楚你应该如何指定TastyPie来返回这些代码。这是我没有找到的TastyPie的功能,还是我必须手动滚动此功能?
答案 0 :(得分:0)
您可以使用额外的反序列化创建父资源:
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
对我来说非常适合。
如果你想处理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版本略有不同或 不同。你必须检查它。
答案 1 :(得分:0)
您必须create your own Serializer class并将其用于资源。
class JsonOnlySerializer(Serializer):
# limit the available formats
formats = ['json']
content_types = {'json': 'application/json'}
# catch the Unsupported exception and raise BadRequest
def deserialize(self, content, format='application/json'):
try:
return super(SafeJsonSerializer, self).deserialize(content, format)
except UnsupportedFormat as e:
raise BadRequest("Unsupported content type (%s)." % format)
然后将其用于资源的配置:
class MyModel(ModelResource):
class Meta:
queryset = MyModel.objects.all()
serializer = JsonOnlySerializer()