過濾是涉及到查詢數(shù)據(jù)的接口才需要過濾功能
公司主營業(yè)務(wù):網(wǎng)站制作、網(wǎng)站建設(shè)、移動網(wǎng)站開發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競爭能力。創(chuàng)新互聯(lián)是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊。公司秉承以“開放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對我們的高要求,感謝他們從不同領(lǐng)域給我們帶來的挑戰(zhàn),讓我們激情的團(tuán)隊有機(jī)會用頭腦與智慧不斷的給客戶帶來驚喜。創(chuàng)新互聯(lián)推出正定免費(fèi)做網(wǎng)站回饋大家。
DRF 中使用的過濾方式:
使用模塊: from rest_framework.filters import SearchFilter
在視圖層中使用內(nèi)置過濾類
前提:需要使用 GenericAPIView
類中的filter_backends
屬性,所以視圖類得繼承 GenericAPIView
class GenericAPIView(views.APIView):
queryset = None
serializer_class = None
lookup_field = 'pk'
lookup_url_kwarg = None
filter_backends = api_settings.DEFAULT_FILTER_BACKENDS
pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
步驟:
from rest_framework.filters import SearchFilter
class BookViewSet(ViewSetMixin, ListAPIView):
queryset = models.Book.objects
serializer_class = BookModelSerializer
authentication_classes = [LoginAuth, ]
# throttle_classes = [IPThrottling, ]
filter_backends = [SearchFilter]
search_fields = ['name', 'price', ]
使用雙下滑的正向查詢方式
class BookViewSet(ViewSetMixin, ListAPIView):
queryset = models.Book.objects
serializer_class = BookModelSerializer
authentication_classes = [LoginAuth, ]
# throttle_classes = [IPThrottling, ]
filter_backends = [SearchFilter, ]
search_fields = ['publish__name', ]
總結(jié):
search
1、安裝: pip install django-filter
2、使用模塊: from django_filters.rest_framework import DjangoFilterBackend
3、在項目配置文件 settings.py 中注冊下載的 app
4、第三方過濾類在filter_backends
字段中寫,filter_fields
字段指定過濾的字段
INSTALLED_APPS = [
...
'django_filters', # 需要注冊應(yīng)用,
]
4、視圖層中使用
class BookViewSet(ViewSetMixin, ListAPIView):
queryset = models.Book.objects
serializer_class = BookModelSerializer
authentication_classes = [LoginAuth, ]
filter_backends = [DjangoFilterBackend, ]
filter_fields = ['name', 'price']
總結(jié):
filter_backends
字段中寫,filter_fields
字段指定過濾的字段GenericAPIView
才能使用&
來表示和的關(guān)系外鍵字段怎么查?
1、新建一個過濾文件,寫一個類繼承BaseFilterBackend
,重寫filter_queryset(self, request, queryset, view)
方法,返回queryset對象,qs對象是過濾后的
2、視圖層使用,只需要指定filter_backend
屬性為自定義類列表
3、查詢過濾,支持模糊查詢(自己定制過濾方式),在filter_queryset
方法自定義過濾規(guī)則
自定義過濾類的書寫:
from rest_framework.filters import BaseFilterBackend
from django.db.models import Q
class Myfilter(BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
# 獲取過濾參數(shù)
qs_name = request.query_params.get('name')
qs_price = request.query_params.get('price')
# title__contains:精確大小寫查詢,SQL中-->like BINARY
# 利用Q查詢構(gòu)造或關(guān)系
if qs_name:
queryset = queryset.filter(name__contains=qs_name)
elif qs_price:
queryset = queryset.filter(price__contains=qs_price)
elif qs_name or qs_price:
queryset = queryset.filter(Q(name__contains=qs_name) | Q(price__contains=qs_price))
return queryset
視圖類:
from app01.filter import Myfilter
class BookViewSet(ViewSetMixin, ListAPIView):
queryset = models.Book.objects
serializer_class = BookModelSerializer
authentication_classes = [LoginAuth, ]
filter_backends = [Myfilter, ]
我們知道過濾的前提條件是視圖繼承了GenericAPIView才能使用,那么在GenericAPIView中的執(zhí)行流程是什么?
1、調(diào)用了GenericAPIView中的filter_queryset方法
2、filter_queryset方法源碼:
def filter_queryset(self, queryset):
for backend in list(self.filter_backends):
queryset = backend().filter_queryset(self.request, queryset, self)
return queryset
'''
1.backend是通過遍歷該類的filter_backends列表的得到的,也就是我們指定的過濾類列表,那么backend就是我們的過濾類
2.通過實(shí)例化得到對象來調(diào)用了類內(nèi)的filter_queryset返回了過濾后的對象
'''
使用模塊:from rest_framework.filters import OrderingFilter
步驟:
filter_backends
屬性的列表中ordering_fields
指定要排序的字段-
號代表倒序,且必須使用ordering
指定排序字段視圖類書寫:
from app01.filter import Myfilter
from rest_framework.filters import OrderingFilter
class BookViewSet(ViewSetMixin, ListAPIView):
queryset = models.Book.objects
serializer_class = BookModelSerializer
authentication_classes = [LoginAuth, ]
# throttle_classes = [IPThrottling, ]
filter_backends = [Myfilter, OrderingFilter, ] # 先過濾后排序
ordering_fields = ['id', 'price']
注意:過濾可以和排序同時使用,但是先執(zhí)行過濾再執(zhí)行排序,提升了代碼的效率(先過濾后排序),因?yàn)槿绻扰判?,那么?shù)據(jù)庫的數(shù)量龐大的話,直接操作了整個數(shù)據(jù)庫,消耗資源,過濾完成后排序只是針對一小部分?jǐn)?shù)據(jù)
分頁只在查詢所有接口中使用
導(dǎo)入分頁類: from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination
DRF 中分頁的三種方式:
步驟:
自定義類,繼承PageNumberPagination
,重寫四個類屬性
注意: 配置在視圖類中,通過pagination_class
指定,必須繼承GenericAPIView才有
分頁類書寫:
from rest_framework.pagination import PageNumberPagination
class BookPagination(PageNumberPagination):
page_size = 3 # 默認(rèn)每頁顯示2條
page_query_param = 'page' # 查詢條件,eg:page=3
page_size_query_param = 'size' # 查詢條件參數(shù)size=5顯示五條
max_page_size = 10 # 每頁最大顯示條數(shù)
視圖層類:
給 pagination_class
屬性賦值分頁類
from app01.page import BookPagination
class BookViewSet(ViewSetMixin, ListAPIView):
queryset = models.Book.objects.all()
serializer_class = BookModelSerializer
authentication_classes = []
filter_backends = [Myfilter, OrderingFilter, ] # 先過濾后排序
ordering_fields = ['id', 'price']
pagination_class = BookPagination
步驟:
分頁類書寫:
from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination
class MyLimitOffset(LimitOffsetPagination):
default_limit = 2 # 默認(rèn)每頁顯示2條
limit_query_param = 'limit' # ?limit=3,查詢出3條
offset_query_param = 'offset' # 偏移量,?offset=2,從第2條后開始
max_limit = 5 # 最大顯示5條
視圖層類:
給 pagination_class
屬性賦值分頁類
from app01.page import BookPagination, MyLimitOffset
class BookViewSet(ViewSetMixin, ListAPIView):
queryset = models.Book.objects.all()
serializer_class = BookModelSerializer
authentication_classes = []
filter_backends = [Myfilter, OrderingFilter, ] # 先過濾后排序
ordering_fields = ['id', 'price']
pagination_class = MyLimitOffset
步驟:
分頁類書寫:
from rest_framework.pagination import CursorPagination
class MyCursor(CursorPagination):
page_size = 3
cursor_query_param = 'cursor'
ordering = 'id'
視圖層類:
給 pagination_class
屬性賦值分頁類
from app01.page import BookPagination, MyLimitOffset, MyCursor
class BookViewSet(ViewSetMixin, ListAPIView):
queryset = models.Book.objects.all()
serializer_class = BookModelSerializer
authentication_classes = []
filter_backends = [Myfilter, ] # 使用了 cursor 游標(biāo)分頁,不要指定排序規(guī)則,會報錯
ordering_fields = ['id', 'price']
pagination_class = MyCursor
查詢方式
http://127.0.0.1:8000/books/?cursor=cD02
注意:分頁類內(nèi)指定了排序,視圖內(nèi)不要寫排序規(guī)則,不然報錯
之前讀APIView源碼的時候,捕獲了全局異常,在執(zhí)行三大認(rèn)證,視圖類的方法時候,如果出了異常,會被全局異常捕獲
以下是APIView
捕獲異常 的流程
1、 APIView源碼
# dispatch方法源碼
except Exception as exc:
response = self.handle_exception(exc)
# handle_exception方法源碼
exception_handler = self.get_exception_handler()
response = exception_handler(exc, context)
2、 默認(rèn)配置文件
get_exception_handler() 調(diào)用的是 views 中的 exception_handler
'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler',
3、views種的exception_handler方法
def exception_handler(exc, context):
if isinstance(exc, Http404):
exc = exceptions.NotFound()
elif isinstance(exc, PermissionDenied):
exc = exceptions.PermissionDenied()
if isinstance(exc, exceptions.APIException):
headers = {}
if getattr(exc, 'auth_header', None):
else:
data = {'detail': exc.detail}
return Response(data, status=exc.status_code, headers=headers)
return None
由上源碼可知,exception_handler(exc, context) 方法,如果報的是已知的錯會返回 Response 對象,未知錯誤返回 None
可以自定義出現(xiàn)異常之后的處理方法和返回數(shù)據(jù)的格式
重寫異常處理方法:
from rest_framework.views import exception_handler
from rest_framework.response import Response
def myexception_handler(exc, context):
# 先執(zhí)行原來的exception_handler幫助我們處理
res = exception_handler(exc, context)
if res:
# res有值代表處理過了APIException對象的異常了,返回的數(shù)據(jù)再定制
res = Response(data={'code': 998, 'msg': res.data.get('detail', '服務(wù)器異常,請聯(lián)系系統(tǒng)管理員')})
# res = Response(data={'code': 998, 'msg': '服務(wù)器異常,請聯(lián)系系統(tǒng)管理員'})
# res.data.get從響應(yīng)中獲取原來的處理詳細(xì)信息
else:
res = Response(data={'code': 999, 'msg': str(exc)})
print(exc) # list index out of range
'''模擬日志處理'''
request = context.get('request') # 當(dāng)次請求的request對象
view = context.get('view') # 當(dāng)次執(zhí)行的視圖類對象
print('錯誤原因:%s,錯誤視圖類:%s,請求地址:%s,請求方式:%s' % (str(exc), str(view), request.path, request.method))
'''結(jié)果:
錯誤原因:list index out of range,錯誤視圖類:<app01.views.TestView object at 0x000001C3B1C7CA58>,請求地址:/test/,請求方式:GET
'''
return res
修改異常的配置路徑:
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'app01.myexception.exception_handler' # 再出異常,會執(zhí)行自己定義的函數(shù)
}
視圖類中報錯就會自動觸發(fā)異常處理:
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.exceptions import APIException
# 測試異常視圖
class Test(APIView):
def get(self,request):
# 1、 其他報錯
# l = [1,2,3]
# print(l[100])
# 2、APIException異常
# raise APIException('APIException errors!')
return Response('success!')
當(dāng)前標(biāo)題:drf 過濾、排序、分頁、異常處理
標(biāo)題來源:http://m.kartarina.com/article20/dsoghco.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站設(shè)計公司、App開發(fā)、網(wǎng)站收錄、建站公司、響應(yīng)式網(wǎng)站、網(wǎng)站營銷
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)