restframework 異常處理及自定義異常
本文轉自https://www.jianshu.com/p/525d477be813
個人做記錄所用
異常
異常處理...允許錯誤處理在程式結構的中心或者高層級的地方被清晰有條理的組織起來。
Exceptions… allow error handling to be organized cleanly in a central or high-level place within the program structure.
— Doug Hellmann, Python Exception Handling Techniques
Rest框架檢視中的異常處理
Exception handling in REST framework views
REST框架的檢視處理了各種異常,並正確地返回了錯誤響應。
REST framework's views handle various exceptions, and deal with returning appropriate error responses.
被處理的異常有:
- Rest框架內部丟擲的
APIException
的子類。 - Django的
Http404
異常。 - Django的
PermissionDenied
異常
針對每種情況,REST框架將返回一個包含了正確的狀態碼和content-type的響應。響應體包含了任何關於錯誤本身的額外細節。
大部分的錯誤響應將在響應體中包含了一個detail
的鍵。
例如下面請求:
DELETE http://api.example.com/foo/bar HTTP/1.1
Accept: application/json
你還可能接收到一個錯誤響應,表明對該資源DELETE
方法不允許的。
HTTP/1.1 405 Method Not Allowed
Content-Type: application/json
Content-Length: 42
{"detail": "Method 'DELETE' not allowed."}
校驗錯誤的處理有些輕微的不同,它會把欄位的名字作為鍵包含進來。如果校驗錯誤沒有被指定到一個特定的欄位,那麼它會使用non_field_errors
作為鍵,或者是你在setting檔案中設定的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."]}
自定義異常處理
你可以實現你的自定義異常處理。可以通過建立一個異常處理函式將API檢視中丟擲的異常轉換成響應物件。這樣一來,你就可以控制你的API使用的錯誤響應格式。
這個異常處理函式必須傳入兩個引數,第一個是要處理的異常,第二個是一個包含了任何額外上下文資訊(例如當前被處理的檢視)的字典。該異常處理函式要麼返回一個Response
物件,要麼在異常無法處理的時候返回None
。如果返回了None
,異常將會被重新丟擲,最後Django會返回一個標準的HTTP 500 ‘伺服器錯誤’的響應。
例如,你可能希望保證所有的錯誤響應體中都包含了HTTP狀態碼,像這樣:
HTTP/1.1 405 Method Not Allowed
Content-Type: application/json
Content-Length: 62
{"status_code": 405, "detail": "Method 'DELETE' not allowed."}
為了更改響應的格式,你可以編寫如下的自定義異常處理函式:
from rest_framework.views import exception_handler
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
引數context沒有被預設的異常處理器使用,但是如果你需要更多的資訊,例如你想獲得當前被處理的檢視,它就能給你援助之手了。通過context['view']
就可以獲取當前檢視。
同時你必須在你的settings中配置異常處理器,顯式地給EXCEPTION_HANDLER
設定你期望的值,例如:
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'my_project.my_app.utils.custom_exception_handler'
}
如果沒有指定,’EXCEPTION_HANDLER‘
預設使用的是REST框架提供的標準的異常處理器:
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler'
}
注意一點,異常處理器僅僅在響應是由丟擲的異常產生時被呼叫。如果由檢視直接返回的響應,它將不會被呼叫,例如HTTP_400_BAD_REQUEST
響應是在序列化校驗失敗時由generic檢視返回的,此時異常處理器就不會被呼叫。
API 引用
APIException
Signature: APIException()
所有在APIView
類中或者@api_view
丟擲的異常的基類。
為了提供自定義異常,自定義個類,繼承自APIException
,並設定.status_code
和.default_detail
屬性。
例如,如果你的API依賴第三方服務,這個服務有時候可能會不可用,你或許可以考慮為"503 Service Unavailable"HTTP響應碼實現一個異常類,你可以這麼做:
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
的時候,如果請求包含了非法的資料,就會丟擲該錯誤。
預設,該異常返回"400 Bad Request"狀態碼。
AuthenticationFailed
Signature: AuthenticationFailed(detail=None)
當請求包含了錯誤的認證資訊的時候丟擲。
Raised when an incoming request includes incorrect authentication.
預設情況下,該異常返回401 Unauthenticated
,但是也有可能返回403 Forbidden
,這取決於使用的認證模式。詳細內容參考authentication documentation
NotAuthenticated
Signature: NotAuthenticated(detail=None)
當未認證的請求許可權驗證失敗時丟擲。
預設情況下,該異常返回401 Unauthenticated
,但是也有可能返回403 Forbidden
,這取決於使用的認證模式。詳細內容參考authentication documentation
PermissionDenied
Signature: PermissionDenied(detail=None)
當一個經認證的請求在許可權校驗失敗時丟擲。
預設返回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
時,沒有解析器來處理請求資料的內容型別時丟擲。
預設返回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
引數是強制的,非可選。 -
detail
引數可以是錯誤細節的列表或者字典,也可以是一個內嵌的資料結構。 - 約定中,你應該匯入序列化器模組並使用完整描述的
ValidationError
格式,這是為了跟Django的內建檢驗錯誤區分開來。例如.raise serializers.ValidationError('This field must be an integer value.')
ValidationError
類應該通過驗證器類為序列化器和欄位校驗使用。它也會在呼叫serializer.is_valid
方法,並指定了raise_exception
時被丟擲。
serializer.is_valid(raise_exception=True)
在generic檢視中使用raise_exception=True
標記,意味著你可以在你的API中全域性複寫校驗錯誤響應的格式。如果你要這麼做,建議你使用一個自定義的異常,上文有描述。
預設情況下,該異常返回400 Bad Request
相關文章
- C#自定義異常 統一異常處理C#
- springboot下新增全域性異常處理和自定義異常處理Spring Boot
- 【Django】DRF自定義異常處理Django
- Java 異常(二) 自定義異常Java
- Spring Cloud Gateway-自定義異常處理SpringCloudGateway
- SpringBoot系列——自定義統一異常處理Spring Boot
- 異常篇——異常處理
- 自定義異常
- Spring Cloud Gateway自定義異常處理Exception HandlerSpringCloudGatewayException
- Java異常處理的兩種方式以及自定義異常的使用方法Java
- bug及異常處理1
- 自定義異常類
- Java自定義異常Java
- springboot自定義異常Spring Boot
- 2024.10.11(自定義異常)
- Dubbo 自定義異常,你是怎麼處理的?
- 異常-throws的方式處理異常
- 異常處理
- python自定義異常,使用raise引發異常PythonAI
- Java 異常表與異常處理原理Java
- Spring Boot 中關於自定義異常處理的套路!Spring Boot
- SpringBoot專案實戰(7):自定義異常處理介面Spring Boot
- 異常-自定義異常的實現和測試
- C#規範整理·異常與自定義異常C#
- Java之自定義異常Java
- React 異常處理React
- JS異常處理JS
- oracle異常處理Oracle
- Python——異常處理Python
- Python異常處理Python
- ThinkPHP 異常處理PHP
- JavaScript 異常處理JavaScript
- JAVA 異常處理Java
- 異常的處理
- golang - 異常處理Golang
- 異常處理2
- 異常處理1
- Java 異常處理Java