一 過濾Filtering
對於列表數據可能需要根據字段進行過濾,我們可以通過添加django-fitlter擴展來增強支持。
1
|
pip install django-filter
|
在配置文件中增加過濾后端的設置:
1 2 3 4 5 6 7 8 9
|
INSTALLED_APPS = [ ... 'django_filters', ]
REST_FRAMEWORK = { ... 'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',) }
|
在視圖中添加filter_fields屬性,指定可以過濾的字段
1 2 3 4 5 6
|
classStudentListView(ListAPIView): queryset = Student.objects.all() serializer_class = StudentSerializer filter_fields = ('age', 'sex')
|
二 排序
對於列表數據,REST framework提供了OrderingFilter過濾器來幫助我們快速指明數據按照指定字段進行排序。
使用方法:
在類視圖中設置filter_backends,使用rest_framework.filters.OrderingFilter
過濾器,REST framework會在請求的查詢字符串參數中檢查是否包含了ordering參數,如果包含了ordering參數,則按照ordering參數指明的排序字段對數據集進行排序。
前端可以傳遞的ordering參數的可選字段值需要在ordering_fields中指明。
示例:
1 2 3 4 5 6 7 8 9
|
classStudentListView(ListAPIView): queryset = Student.objects.all() serializer_class = StudentModelSerializer filter_backends = [OrderingFilter] ordering_fields = ('id', 'age')
|
如果需要在過濾以后再次進行排序,則需要兩者結合!
1 2 3 4 5 6 7 8 9 10 11 12
|
from rest_framework.generics import ListAPIView from students.models import Student from .serializers import StudentModelSerializer from django_filters.rest_framework import DjangoFilterBackend class Student3ListView(ListAPIView): queryset = Student.objects.all() serializer_class = StudentModelSerializer filter_fields = ('age', 'sex')
|
REST framework提供了分頁的支持。
我們可以在配置文件中設置全局的分頁方式,如:
1 2 3 4
|
REST_FRAMEWORK = { 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 'PAGE_SIZE': 100 }
|
也可通過自定義Pagination類,來為視圖添加不同分頁行為。在視圖中通過pagination_clas
屬性來指明。
1 2 3 4 5 6 7 8
|
classLargeResultsSetPagination(PageNumberPagination): page_size = 1000 page_size_query_param = 'page_size' max_page_size = 10000 class BookDetailView(RetrieveAPIView): queryset = BookInfo.objects.all() serializer_class = BookInfoSerializer pagination_class = LargeResultsSetPagination
|
注意:如果在視圖內關閉分頁功能,只需在視圖內設置
1
|
pagination_class = None
|
可選分頁器
1) PageNumberPagination
前端訪問網址形式:
可以在子類中定義的屬性:
- page_size 每頁數目
- page_query_param 前端發送的頁數關鍵字名,默認為”page”
- page_size_query_param 前端發送的每頁數目關鍵字名,默認為None
- max_page_size 前端最多能設置的每頁數量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
|
from rest_framework.pagination import PageNumberPagination
classPager(APIView): defget(self,request,*args,**kwargs):
ret=models.Book.objects.all()
page=PageNumberPagination()
page_list=page.paginate_queryset(ret,request,view=self)
ser=BookSerializer1(instance=page_list,many=True) return Response(ser.data)
classMypage(PageNumberPagination): page_size = 2 page_query_param = 'page'
page_size_query_param = 'size'
max_page_size = 5 classPager(APIView): defget(self,request,*args,**kwargs):
ret=models.Book.objects.all()
page=Mypage()
page_list=page.paginate_queryset(ret,request,view=self)
ser=BookSerializer1(instance=page_list,many=True)
return page.get_paginated_response(ser.data)
from rest_framework.pagination import PageNumberPagination classStandardPageNumberPagination(PageNumberPagination):
page_size = 2
page_size_query_param = "size" max_page_size = 10
page_query_param = "p"
classStudentAPIView(ListAPIView): queryset = Student.objects.all() serializer_class = StudentModelSerializer pagination_class = StandardPageNumberPagination
|
2)LimitOffsetPagination
前端訪問網址形式:
1
|
GET http://127.0.0.1/four/students/?limit=100&offset=400
|
可以在子類中定義的屬性:
- default_limit 默認限制,默認值與
PAGE_SIZE
設置一直
- limit_query_param limit參數名,默認’limit’
- offset_query_param offset參數名,默認’offset’
- max_limit 最大limit限制,默認None
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
from rest_framework.pagination import LimitOffsetPagination
classPager(APIView): defget(self,request,*args,**kwargs):
ret=models.Book.objects.all()
page=LimitOffsetPagination()
page_list=page.paginate_queryset(ret,request,view=self)
ser=BookSerializer1(instance=page_list,many=True)
return Response(ser.data)
from rest_framework.pagination import LimitOffsetPagination classStandardLimitOffsetPagination(LimitOffsetPagination):
default_limit = 2 limit_query_param = "size" offset_query_param = "start"
classStudentAPIView(ListAPIView): queryset = Student.objects.all() serializer_class = StudentModelSerializer
pagination_class = StandardLimitOffsetPagination
|
3)CursorPagination
前端訪問網址形式:
1
|
GET http://127.0.0.1/four/students/?cursor=cD0xNQ%3D%3D
|
可以在子類中定義的屬性:
- cursor_query_param:默認查詢字段,不需要修改
- page_size:每頁數目
- ordering:按什么排序,需要指定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
from rest_framework.pagination import CursorPagination
|
應用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination class MyPageNumberPagination(PageNumberPagination): page_size = 2 page_query_param = 'page'
|
四 異常處理 Exceptions
REST framework提供了異常處理,我們可以自定義異常處理函數。
4.1 使用方式
1 2 3 4 5 6 7 8 9 10 11
|
from rest_framework.views import exception_handler
defcustom_exception_handler(exc, context):
response = exception_handler(exc, context)
if response isNone: response.data['status_code'] = response.status_code
return response
|
在配置文件中聲明自定義的異常處理
1 2 3
|
REST_FRAMEWORK = { 'EXCEPTION_HANDLER': 'my_project.my_app.utils.custom_exception_handler' }
|
如果未聲明,會采用默認的方式,如下
rest_frame/settings.py
1 2 3
|
REST_FRAMEWORK = { 'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler' }
|
4.2 案例
補充上處理關於數據庫的異常
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
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
|
4.3 REST framework定義的異常
- APIException 所有異常的父類
- ParseError 解析錯誤
- AuthenticationFailed 認證失敗
- NotAuthenticated 尚未認證
- PermissionDenied 權限決絕
- NotFound 未找到
- MethodNotAllowed 請求方式不支持
- NotAcceptable 要獲取的數據格式不支持
- Throttled 超過限流次數
- ValidationError 校驗失敗
也就是說,很多的沒有在上面列出來的異常,就需要我們在自定義異常中自己處理了。