文档章节

Django REST framework的各种技巧——6.异常处理

duoduo3_69
 duoduo3_69
发布于 2016/02/01 19:22
字数 653
阅读 269
收藏 1

restframework内置了基本的异常处理,然而并不够用

Django REST framework的各种技巧【目录索引】

异常处理应该考虑的事情

  • 异常时为了保持api的一致,应该返回json
  • error_code
  • 给开发看的error_message
  • 给用户看的message

开始怼代码

源码中的异常处理,可见是不符合需求的。

def exception_handler(exc, context):
    """ 
    Returns the response that should be used for any given exception.

    By default we handle the REST framework `APIException`, and also
    Django's built-in `Http404` and `PermissionDenied` exceptions.

    Any unhandled exceptions may return `None`, which will cause a 500 error
    to be raised.
    """
    if isinstance(exc, exceptions.APIException):
        headers = {}
        if getattr(exc, 'auth_header', None):
            headers['WWW-Authenticate'] = exc.auth_header
        if getattr(exc, 'wait', None):
            headers['Retry-After'] = '%d' % exc.wait

        if isinstance(exc.detail, (list, dict)):
            data = exc.detail
        else:
            data = {'detail': exc.detail}

        set_rollback()
        return Response(data, status=exc.status_code, headers=headers)
    elif isinstance(exc, Http404):
        msg = _('Not found.')
        data = {'detail': six.text_type(msg)}

        set_rollback()
        return Response(data, status=status.HTTP_404_NOT_FOUND)

    elif isinstance(exc, PermissionDenied):
        msg = _('Permission denied.')
        data = {'detail': six.text_type(msg)}

        set_rollback()
        return Response(data, status=status.HTTP_403_FORBIDDEN)

    # Note: Unhandled exceptions will raise a 500 error.
    return None        

实现想要的handler

注意我在handler最后一行注释掉的代码,一定不能抓最后的异常,这样log的信息会没有各种堆栈,非常不全

class Error(Exception):

    def __init__(self, err_code, err_message='Internal Server Error',
                 message=u'服务器异常', status_code=status.HTTP_400_BAD_REQUEST):
        self.err_code = err_code
        self.err_message = err_message
        self.message = message
        self.status_code = status_code

    def __unicode__(self):
            return u'[Error] %d: %s(%d)' % (self.err_code, self.err_message, self.status_code)

    def getResponse(self):
        return ErrorResponse(self.err_code, self.err_message, self.message, self.status_code)


def ErrorResponse(err_code=errors.SYSTEM_ERROR, err_message='Internal Server Error',
                  message=u'服务器异常', status=status.HTTP_400_BAD_REQUEST, headers=None):
    err = { 
        'error_code': err_code,
        'error': err_message,
        'message': message,
    }   
    return Response(err, status, headers=headers)
    
def custom_exception_handler(exc, context):

    if isinstance(exc, Error):
        set_rollback()
        return ErrorResponse(exc.err_code, exc.err_message, exc.message, status=exc.status_code)

    if isinstance(exc, (ForeignObjectRelDeleteError, ModelDontHaveIsActiveFiled)):
        set_rollback()
        return ErrorResponse(errors.PermissionDenied, unicode(exc), u'抱歉, 已有其他数据与之关联, 禁止删除', status=status.HTTP_403_FORBIDDEN)

    if isinstance(exc, (RestPermissionDenied, PermissionDenied)):
        msg = _('Permission denied.')
        data = {
            'detail': six.text_type(msg)
        }
        exc_message = str(exc)
        if 'CSRF' in exc_message:
            data['detail'] = exc_message

        set_rollback()
        return ErrorResponse(errors.PermissionDenied, data, u'opps, 您没有对应的权限', status=status.HTTP_403_FORBIDDEN)    
    ....
        log.error(exc)
    # Note: Unhandled exceptions will raise a 500 error.
    #return ErrorResponse(errors.SYSTEM_ERROR, 'Internal Server Error', status.HTTP_500_INTERNAL_SERVER_ERROR)

然后在settings.py中加上 'EXCEPTION_HANDLER': 'api.exception_handler.custom_exception_handler',

通过这样的实现你就可以直接在代码中丢异常了,而前端收到的是一个http code为400的json response

    @POST('name', validators='required')
    def create(self, request, name, *args, **kwargs):
        try:
            Term.objects.get(name=name, is_active=True)
            raise Error(errors.Exist, err_message=u'已存在对应的年份', message=u'已存在对应的年份')
        except Term.DoesNotExist:
            pass
        return super(TermsView, self).create(request, *args, **kwargs)

关于上面的500的json方式

使用django的自定义404,500handler的方式解决

url.py里面加上 handler500 = 'service.views.render_500'

def render_500(request):
    if request.is_ajax():
        err = { 
            'error_code': errors.SYSTEM_ERROR,
            'error': 'Internal Server Error',
            'message': 'Internal Server Error',
        }   
        return JsonResponse(err, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    return redirect('/error/?c=500')

© 著作权归作者所有

duoduo3_69
粉丝 90
博文 57
码字总数 83746
作品 0
青岛
程序员
私信 提问
Django REST framework的各种技巧【目录索引】

为了防止各位看同学不好找,在这边丢了个目录过来,因为以后可能继续写 目录 [Django REST framework的各种技巧——1.基础讲解][1] [Django REST framework的各种技巧——2.serializer][2] ...

duoduo3_69
2016/02/01
582
0
Django REST framework的各种技巧【目录索引】

为了防止各位看同学不好找,在这边丢了个目录过来,因为以后可能继续写 目录 Django REST framework的各种技巧——1.基础讲解 Django REST framework的各种技巧——2.serializer Django RES...

D咄咄
2017/11/29
0
0
Django REST framework的各种技巧——6.异常处理

restframework内置了基本的异常处理,然而并不够用 Django REST framework的各种技巧【目录索引】 异常处理应该考虑的事情 异常时为了保持api的一致,应该返回json error_code 给开发看的err...

D咄咄
2017/11/29
0
0
Django REST framework的各种技巧——1.基础讲解

写在最上面的话 django是一个神奇的框架,而restframework又是遵循了这个框架的另一个神奇的框架,然而由于restframework的文档稀烂无比,很多时候你必须看源码才能写出科学的代码,这挡住了...

D咄咄
2017/11/29
0
0
Django REST framework的各种技巧——4.Generic View

generic view是django神奇的地方,而restframework遵循了这个powerful的机制 Django REST framework的各种技巧【目录索引】 写在上面 所有的代码都是在下面的两个版本来做的 一个之前的blog,...

D咄咄
2017/11/29
0
0

没有更多内容

加载失败,请刷新页面

加载更多

jquery底层函数-jQuery.ajaxSetup()

jQuery.ajaxSetup( options )返回: 描述: 为以后要用到的Ajax请求设置默认的值 添加的版本: 1.1jQuery.ajaxSetup( options ) options 类型: PlainObject 一个用来配置Ajax请求的"{键:值}"对,......

前端老手
36分钟前
7
0
Qt编写自定义控件56-波浪曲线

一、前言 波浪曲线控件,其实是之前一个水波进度条控件的一个核心,其实就是利用正弦曲线来生成对应的坐标进行绘制,把这个功能单独提取出来,是为了更详细的研究各种正弦余弦等拓展效果,当...

飞扬青云
43分钟前
6
0
深入理解计算机系统cp1:存储单位与编码

摘要: 理解计算机是如何存储数据的。 原文:深入理解计算机系统cp1:存储单位与编码 作者:Chor Fundebug经授权转载,版权归原作者所有。 1. 存储单位 位:即 bit,表示二进制位,要么是 0 ...

Fundebug
45分钟前
6
0
Python查询比特币实时价格

在本文中我们将学习如何使用使用coinmarketcap提供的比特币行情API,编写Python程序来获取像比特币、莱特币或以太币之类的区块链数字货币的实时行情/实时价格。 1、比特币行情API调用代码 我...

汇智网教程
今天
8
0
爬虫平台Crawlab核心原理--自动提取字段算法

⚠注意: 可配置爬虫现在仅在Python版本(v0.2.1-v0.2.4)可用,在最新版本Golang版本(v0.3.0)还暂时不可用,后续会加上,请关注近期更新 背景 实际的大型爬虫开发项目中,爬虫工程师会被要...

tikazyq
今天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部