首頁技術(shù)文章正文

Django Rest框架視圖中的異常處理

更新時間:2018-08-31 來源:黑馬程序員技術(shù)社區(qū) 瀏覽量:

  REST框架的視圖處理了各種異常,并正確地返回了錯誤響應(yīng)。

  被處理的異常有:

  Rest框架內(nèi)部拋出的APIException的子類。

  Django的Http404異常。

  Django的PermissionDenied異常

  針對每種情況,REST框架將返回一個包含了正確的狀態(tài)碼和content-type的響應(yīng)。響應(yīng)體包含了任何關(guān)于錯誤本身的額外細節(jié)。

  大部分的錯誤響應(yīng)將在響應(yīng)體中包含了一個detail的鍵。

  例如下面請求:

  DELETE http://api.example.com/foo/bar HTTP/1.1

  Accept: application/json

  你還可能接收到一個錯誤響應(yīng),表明對該資源DELETE方法不允許的。

  HTTP/1.1 405 Method Not AllowedContent-Type: application/json

  Content-Length: 42

  {"detail": "Method 'DELETE' not allowed."}

  校驗錯誤的處理有些輕微的不同,它會把字段的名字作為鍵包含進來。如果校驗錯誤沒有被指定到一個特定的字段,那么它會使用non_field_errors作為鍵,或者是你在setting文件中設(shè)定的NON_FIELD_ERRORS_KEY任意字符串的值。

  任何校驗錯誤將類似下面的形式:

  HTTP/1.1 400 Bad Request

  Content-Type: application/json

  Content-Length: 94

  {"amount": ["A valid integer is required."], "description": ["This field may not be blank."]}

  自定義異常處理

  你可以實現(xiàn)你的自定義異常處理。可以通過創(chuàng)建一個異常處理函數(shù)將API視圖中拋出的異常轉(zhuǎn)換成響應(yīng)對象。這樣一來,你就可以控制你的API使用的錯誤響應(yīng)格式。

  這個異常處理函數(shù)必須傳入兩個參數(shù),第一個是要處理的異常,第二個是一個包含了任何額外上下文信息(例如當前被處理的視圖)的字典。該異常處理函數(shù)要么返回一個Response對象,要么在異常無法處理的時候返回None。如果返回了None,異常將會被重新拋出,最后Django會返回一個標準的HTTP 500 ‘服務(wù)器錯誤’的響應(yīng)。

  例如,你可能希望保證所有的錯誤響應(yīng)體中都包含了HTTP狀態(tài)碼,像這樣:

  HTTP/1.1 405 Method Not Allowed

  Content-Type: application/json

  Content-Length: 62

  {"status_code": 405, "detail": "Method 'DELETE' not allowed."}

  為了更改響應(yīng)的格式,你可以編寫如下的自定義異常處理函數(shù):

  from rest_framework.views import exception_handlerdef custom_exception_handler(exc, context): # Call REST framework's default exception handler first, # to get the standard error response. response = exception_handler(exc, context) # Now add the HTTP status code to the response. if response is not None: response.data['status_code'] = response.status_code return response

  from rest_framework.views import exception_handle

  def custom_exception_handler(exc, context):

  # Call REST framework's default exception handler first,

  # to get the standard error response.

  response = exception_handler(exc, context)

  # Now add the HTTP status code to the response.

  if response is not None:

  response.data['status_code'] = response.status_code

  return response

  參數(shù)context沒有被默認的異常處理器使用,但是如果你需要更多的信息,例如你想獲得當前被處理的視圖,它就能給你援助之手了。通過context['view']就可以獲取當前視圖。

  同時你必須在你的settings中配置異常處理器,顯式地給EXCEPTION_HANDLER設(shè)置你期望的值,例如:

  REST_FRAMEWORK = {

  'EXCEPTION_HANDLER': 'my_project.my_app.utils.custom_exception_handler'

  }

  如果沒有指定,’EXCEPTION_HANDLER‘默認使用的是REST框架提供的標準的異常處理器:

  REST_FRAMEWORK = {

  'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler'

  }

  注意一點,異常處理器僅僅在響應(yīng)是由拋出的異常產(chǎn)生時被調(diào)用。如果由視圖直接返回的響應(yīng),它將不會被調(diào)用,例如HTTP_400_BAD_REQUEST響應(yīng)是在序列化校驗失敗時由generic視圖返回的,此時異常處理器就不會被調(diào)用。

  API 引用APIException

  Signature: APIException()

  所有在APIView類中或者@api_view拋出的異常的基類。

  為了提供自定義異常,自定義個類,繼承自APIException,并設(shè)置.status_code和.default_detail屬性。

  例如,如果你的API依賴第三方服務(wù),這個服務(wù)有時候可能會不可用,你或許可以考慮為”503 Service Unavailable”HTTP響應(yīng)碼實現(xiàn)一個異常類,你可以這么做:

  from rest_framework.exceptions import APIException

  class ServiceUnavailable(APIException):

  status_code = 503

  default_detail = 'Service temporarily unavailable, try again later.'

  ParseError

  Signature: ParseError(detail=None)

  在訪問request.data的時候,如果請求包含了非法的數(shù)據(jù),就會拋出該錯誤。

  默認,該異常返回”400 Bad Request”狀態(tài)碼。

  AuthenticationFailed

  Signature: AuthenticationFailed(detail=None)

  當請求包含了錯誤的認證信息的時候拋出。

  Raised when an incoming request includes incorrect authentication.

  默認情況下,該異常返回401 Unauthenticated,但是也有可能返回403 Forbidden,這取決于使用的認證模式。詳細內(nèi)容參考authentication documentation

  NotAuthenticated

  Signature: NotAuthenticated(detail=None)

  當未認證的請求權(quán)限驗證失敗時拋出。

  默認情況下,該異常返回401 Unauthenticated,但是也有可能返回403 Forbidden,這取決于使用的認證模式。詳細內(nèi)容參考authentication documentation

  PermissionDenied

  Signature: PermissionDenied(detail=None)

  當一個經(jīng)認證的請求在權(quán)限校驗失敗時拋出。

  默認返回403 Forbidden

  NotFound

  Signature: NotFound(detail=None)

  當給定的URL不存在時拋出。該異常等效于標準的DjangoHttp404異常。

  默認返回404 Not Found.

  MethodNotAllowed

  Signature: MethodNotAllowed(method, detail=None)

  在視圖中沒有與請求匹配的處理方法時拋出。

  默認返回405 Method Not Allowed

  NotAcceptable

  Signature: NotAcceptable(detail=None)

  當請求的接受頭不滿足任何可用的渲染器時拋出。

  默認返回406 Not Acceptable

  UnsupportedMediaType

  Signature: UnsupportedMediaType(media_type, detail=None)

  當訪問request.data時,沒有解析器來處理請求數(shù)據(jù)的內(nèi)容類型時拋出。

  默認返回415 Unsupported Media Type

  Throttled

  Signature: Throttled(wait=None, detail=None)

  當請求超過最大限制時拋出。

  默認返回429 Too Many Requests

  ValidationError

  Signature: ValidationError(detail)

  ValidationError跟其他的APIException類稍微有些不同:

  The ValidationError exception is slightly different from the other APIException classes:

  detail參數(shù)是強制的,非可選。

  detail參數(shù)可以是錯誤細節(jié)的列表或者字典,也可以是一個內(nèi)嵌的數(shù)據(jù)結(jié)構(gòu)。

  約定中,你應(yīng)該導入序列化器模塊并使用完整描述的ValidationError格式,這是為了跟Django的內(nèi)置檢驗錯誤區(qū)分開來。例如.raise serializers.ValidationError('This field must be an integer value.')

  ValidationError類應(yīng)該通過驗證器類為序列化器和字段校驗使用。它也會在調(diào)用serializer.is_valid方法,并指定了raise_exception時被拋出。

  serializer.is_valid(raise_exception=True)

  serializer.is_valid(raise_exception=True)

  在generic視圖中使用raise_exception=True標記,意味著你可以在你的API中全局復寫校驗錯誤響應(yīng)的格式。如果你要這么做,建議你使用一個自定義的異常,上文有描述。

  默認情況下,該異常返回400 Bad Request



作者:黑馬程序員技術(shù)社區(qū)
首發(fā):http://python.itheima.com/

分享到:
在線咨詢 我要報名
和我們在線交談!