drf 第三方模組的過率 排序 處理異常 自己封裝的response物件
阿新 • • 發佈:2021-06-24
一 過濾Filtering
對於列表資料可能需要根據欄位進行過濾,我們可以通過新增django-fitlter擴充套件來增強支援。
安裝
pip install django-filter 註冊 INSTALLED_APPS = [ ... 'django_filters', # 需要註冊應用, ]
全域性配置
REST_FRAMEWORK = { ... 'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',) } # 在檢視中新增filter_fields屬性,指定可以過濾的欄位class StudentListView(ListAPIView): queryset = Student.objects.all() serializer_class = StudentSerializer filter_fields = ('age', 'sex') # 127.0.0.1:8000/four/students/?sex=1
區域性配置
from django_filters.rest_framework import DjangoFilterBackend class StudentListView(ListAPIView): ... filter_backends= [DjangoFilterBackend,] filter_fields = ('age', 'sex')
二 排序
對於列表資料,REST framework提供了OrderingFilter過濾器來幫助我們快速指明資料按照指定欄位進行排序。
使用方法:
在類檢視中設定filter_backends,使用rest_framework.filters.OrderingFilter
過濾器,REST framework會在請求的查詢字串引數中檢查是否包含了ordering引數,如果包含了ordering引數,則按照ordering引數指明的排序欄位對資料集進行排序。
前端可以傳遞的ordering引數的可選欄位值需要在ordering_fields中指明。
示例:
from rest_framework.generics import ListAPIView from rest_framework.filters import OrderingFilter from app01.models import Book from app01.ser import BookSerializer class Book2View(ListAPIView): queryset = Book.objects.all() serializer_class = BookSerializer filter_backends = [OrderingFilter] ordering_fields = ('id', 'price') #使用 http://127.0.0.1:8000/books2/?ordering=-price http://127.0.0.1:8000/books2/?ordering=price http://127.0.0.1:8000/books2/?ordering=-id -id 表示針對id欄位進行倒序排序 id 表示針對id欄位進行升序排序
如果需要在過濾以後再次進行排序,則需要兩者結合!
from django_filters.rest_framework import DjangoFilterBackend class Book2View(ListAPIView): queryset = Book.objects.all() serializer_class = BookSerializer filter_fields = ('id', 'price') # 過濾 # 因為區域性配置會覆蓋全域性配置,所以需要重新把過濾元件核心類再次宣告, # 否則過濾功能會失效 filter_backends = [OrderingFilter,DjangoFilterBackend] # 過濾要寫在排序之後 ordering_fields = ('id', 'prcie') #排序
三 異常處理 Exceptions
REST framework提供了異常處理,我們可以自定義異常處理函式。
3.1 使用方式
from rest_framework.views import exception_handler def my_exception_handler(exc, context): # 先呼叫REST framework預設的異常處理方法獲得標準錯誤響應物件 response = exception_handler(exc, context) # 在此處補充自定義的異常處理 if not response: if isinstance(exc, ZeroDivisionError): return Response(data={'status': 777, 'msg': "除以0的錯誤" + str(exc)}, status=status.HTTP_400_BAD_REQUEST) return Response(data={'status':999,'msg':str(exc)},status=status.HTTP_400_BAD_REQUEST) else: return Response(data={'status':888,'msg':response.data.get('detail')},status=status.HTTP_400_BAD_REQUEST)
在配置檔案中宣告自定義的異常處理
REST_FRAMEWORK = { 'EXCEPTION_HANDLER': 'app01.app_auth.my_exception_handler', }
3.2 案例
補充上處理關於資料庫的異常
from rest_framework.views import exception_handler from rest_framework.response import Response from rest_framework.views import exception_handler as drf_exception_handler from rest_framework import status from django.db import DatabaseError def exception_handler(exc, context): response = drf_exception_handler(exc, context) if response is None: view = context['view'] print('[%s]: %s' % (view, exc)) if isinstance(exc, DatabaseError): response = Response({'detail': '伺服器內部錯誤'}, status=status.HTTP_507_INSUFFICIENT_STORAGE) else: response = Response({'detail': '未知錯誤'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR) return response # 在setting.py中配置 REST_FRAMEWORK = { 'EXCEPTION_HANDLER': 'app01.ser.exception_handler' }
3.3 REST framework定義的異常
- APIException 所有異常的父類
- ParseError 解析錯誤
- AuthenticationFailed 認證失敗
- NotAuthenticated 尚未認證
- PermissionDenied 許可權決絕
- NotFound 未找到
- MethodNotAllowed 請求方式不支援
- NotAcceptable 要獲取的資料格式不支援
- Throttled 超過限流次數
- ValidationError 校驗失敗
也就是說,很多的沒有在上面列出來的異常,就需要我們在自定義異常中自己處理了。
四 封裝Response物件(重要)
為了讓放回的資料有一定的格式我們要使用自己封裝的Response物件
from rest_framework.response import Response class APIResponse(Response): def __init__(self,code=100,msg='成功',data=None,status=None,headers=None,**kwargs): dic = {'code': code, 'msg': msg} if data: dic = {'code': code, 'msg': msg,'data':data} dic.update(kwargs) super().__init__(data=dic, status=status,headers=headers) # 使用 return APIResponse(data={"name":'lqz'},token='dsafsdfa',aa='dsafdsafasfdee') return APIResponse(data={"name":'lqz'}) return APIResponse(code='101',msg='錯誤',data={"name":'lqz'},token='dsafsdfa',aa='dsafdsafasfdee',header={})