python - Django TastyPie : how do I return something other than 500 for UnsupportedFormat?

标签 python json django http tastypie

使用 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/

相关文章:

python - UTF-16 转 Ascii 忽略十进制值大于 127 的字符

java - Gson StackOverflowError

javascript - Bootstrap 轮播在鼠标悬停或单击之前不会滑动

json - RestClientException : Could not extract response. 找不到合适的 HttpMessageConverter

python - Django:除了临时 session 之外,如何在基于类的 View 中设置(永久)cookie?

刷新后重新提交 django 表单

python - 为什么在使用带有 .append() 方法的 map() 时返回四个列表

python - 带有 swig 的 python 中的段错误(核心转储),但是当我更改变量名称时它会起作用

python - 如何在不使用多线程的情况下显示进度

python - form.is_valid() 为 false 时如何访问数据