django rest-framework里的异常处理上下文

django rest-framework里的异常处理
在rest-framework里的认证过程中:

class APIView(View):
    def perform_authentication(self, request):
        request.user
class Request(object):
    @property
    def user(self):
	        if not hasattr(self, '_user'):
	        with wrap_attributeerrors():
	            self._authenticate()
	    return self._user

在request类的user方法里,先判断了是否有_user属性,然后开启了一个上下文with wrap_attributeerrors()。

@contextmanager
def wrap_attributeerrors():
    try:
        yield
    except AttributeError:
        info = sys.exc_info()
        exc = WrappedAttributeError(str(info[1]))
        six.reraise(type(exc), exc, info[2])

这里的原函数是一个生成器,而with wrap_attributeerrors是一个用contextlib中的contextmanager装饰器装饰的一个上下文管理器,返回的是一个_GeneratorContextManager对象,而这个对象中重写了__enter__和__exit__方法,因此当with wrap_attributeerrors()时,调用的是_GeneratorContextManager中的__enter__,而这个方法里调用了原函数的next()方法,因此相当于启动了该生成器。然后回来执行上下文中的代码,如果出现异常,则会执行_GeneratorContextManager中的__exit__,也就是再执行一次make_context.next()函数,所以先会用自己所定义的异常处理方式来处理异常,然后再处理其他异常。

你可能感兴趣的:(django rest-framework里的异常处理上下文)