目錄
- 一、過濾
- 二、排序
- 三、分頁
- PageNumberPagination
- LimitOffsetPagination
- CursorPagination
- 繼承APIView使用方法
- 四、異常處理
- 五、封裝Response對象
- 總結(jié)
一、過濾
對于列表數(shù)據(jù)要通過字段來進行過濾,就需要添加 django-filter 模塊
使用方法:
# 1、注冊,在app中注冊 settings.py
INSTALLED_APPS = [
'django_filters',
]
# 2、settings.py 配置
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': (
'django_filters.rest_framework.DjangoFilterBackend',
)
}
# 3、在視圖中添加filter_fields屬性,指定過濾的字段
class BooksView(ModelViewSet):
queryset = Books.objects.all()
serializer_class = BooksSerializer
filter_fields = ('title',) # 配置可以按照哪個字段來過濾
# http://127.0.0.1:8000/books/?title=紅樓夢
二、排序
排序可以使用 Rest Framework 提供的 OrderingFilter 來快速指明數(shù)據(jù)按指定字段進行排序
使用方法:
# 1、首先視圖中設(shè)置filter_backends=[OrderingFilter]
# 2、然后再視圖中添加 ordering_fields 屬性,指定排序字段
from rest_framework.filters import OrderingFilter
class BooksView(ModelViewSet):
queryset = Books.objects.all()
serializer_class = BooksSerializer
filter_backends = [OrderingFilter] # 第一步
ordering_fields = ['price','id'] # 第二步
# http://127.0.0.1:8000/books/?ordering=id 通過ordering查看有無指明排序的字段,并通過字段來排序
# -id 表示針對id字段進行倒序排序
# id 表示針對id字段進行升序排序
三、分頁
首先 Rest Framework 提供了三種分頁方式,并且
- PageNumberPagination
- LimitOffsetPagination
- CursorPagination
使用方式一:可以直接繼承使用,但是配置參數(shù)需要在settings.py里面配置
使用方式二:通過子類繼承父類分頁器使用,直接在子類中修改父類的參數(shù)(推薦)
PageNumberPagination
子類中的屬性:
- page_size:每頁數(shù)目
- page_query_param:前端發(fā)送的頁數(shù)關(guān)鍵字,默認“page”
- page_size_query_param:前端發(fā)送每頁數(shù)目關(guān)鍵字名,默認None
- max_page_size:前端最多能設(shè)置的每頁數(shù)量
如何使用:
from rest_framework.generics import ListAPIView
from rest_framework.pagination import PageNumberPagination
from app01.models import Books
from app01.ser import BooksSerializer
# 第一步:
class BookPageNumberPagination(PageNumberPagination):
page_size = 3 # 每頁條數(shù)
page_query_param = 'page' # 查詢第幾頁的key
page_size_query_param = 'size' # 每一頁顯示的條數(shù)
max_page_size = 5 # 每頁最大條數(shù)
class BookView(ListAPIView):
queryset = Books.objects.all()
serializer_class = BooksSerializer
# 第二步:分頁配置
pagination_class = BookPageNumberPagination
# url:http://127.0.0.1:8000/books/?page=1size=5 查詢第1頁,一共顯示五條數(shù)據(jù)
LimitOffsetPagination
子類中的屬性:
- default_limit:默認限制,默認值與PAGE_SIZE設(shè)置一致
- limit_query_param:limit參數(shù)名,默認'limit'
- offset_query_param:offset參數(shù)名,默認'offset'
- max_limit:最大limit限制,默認None
如何使用:
from rest_framework.generics import ListAPIView
from rest_framework.pagination import LimitOffsetPagination
from app01.models import Books
from app01.ser import BooksSerializer
# 第一步:
class BookLimitOffsetPagination(LimitOffsetPagination):
default_limit = 3 # 每頁條數(shù)
limit_query_param = 'limit' # 往后拿幾條
offset_query_param = 'offset' # 從第幾條往后拿幾條的標桿
max_limit = 5 # 每頁最大拿幾條
class BookView(ListAPIView):
queryset = Books.objects.all()
serializer_class = BooksSerializer
# 第二步:分頁配置
pagination_class = BookLimitOffsetPagination
# url:http://127.0.0.1:8000/books/?limit=3offset=4 從第三條開始往后拿4條數(shù)據(jù)
CursorPagination
子類中的屬性:
- cursor_query_param:默認查詢字段,不需要修改
- page_size:每頁數(shù)目
- ordering:按什么排序,需要指定
如何使用:
CursorPagination的查詢速度快,但是卻不能定位到第幾頁這樣查,要么往前查,要么往后查。
from rest_framework.generics import ListAPIView
from rest_framework.pagination import CursorPagination
from app01.models import Books
from app01.ser import BooksSerializer
# 第一步:
class BookCursorPagination(CursorPagination):
cursor_query_param = 'cursor' # 每頁查詢的key
page_size = 3 # 每頁顯示條數(shù)
ordering = 'id' # 排序字段
class BookView(ListAPIView):
queryset = Books.objects.all()
serializer_class = BooksSerializer
# 第二步:分頁配置
pagination_class = BookCursorPagination
# url:http://127.0.0.1:8000/books/?cursor=cD0z
繼承APIView使用方法
像方式一,方式二這樣使用的話,就要視圖類是繼承 ListAPIView 然后直接配置就可以了
但是如果視圖類繼承的是 GenericAPIView 或者 APIView 的話,就需要用另一種方式了:
使用方法:
# 1、定義一個分頁器
class BookPageNumberPagination(PageNumberPagination):
page_size = 3 # 每頁條數(shù)
page_query_param = 'page' # 查詢第幾頁的key
page_size_query_param = 'size' # 每一頁顯示的條數(shù)
max_page_size = 5 # 每頁最大條數(shù)
class BookView(APIView):
def get(self, request, *args, **kwargs):
book_list = Books.objects.all()
# 2、實例化得到一個分頁器對象
page_obj = BookPageNumberPagination()
# 3、調(diào)用paginate_queryset返回每一頁的數(shù)據(jù)
book_list = page_obj.paginate_queryset(book_list, request, view=self)
# 4、獲取上一頁下一頁鏈接
next_url = page_obj.get_next_link()
previous_url = page_obj.get_previous_link()
# 5、序列化
book_ser = BooksSerializer(book_list, many=True)
# 6、加入響應信息中
data = {'next_url': next_url, 'previous_url': previous_url, 'data': book_ser.data}
return Response(data=data)
四、異常處理
異常處理主要是用來統(tǒng)一接口返回
源碼分析
異常處理在APIView的api_settings已經(jīng)配置好了
'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler',
def exception_handler(exc, context):
# 先判斷是不是404
if isinstance(exc, Http404): # exc是異常信息的異常對象
exc = exceptions.NotFound()
# 然后判斷是不是權(quán)限的問題
elif isinstance(exc, PermissionDenied):
exc = exceptions.PermissionDenied() # 比如權(quán)限問題會返回一個字典
# 在判斷你拋出的是不是API的異?!?gt;認證權(quán)限這些都是繼承了API的異常
if isinstance(exc, exceptions.APIException):
headers = {}
if getattr(exc, 'auth_header', None):
headers['WWW-Authenticate'] = exc.auth_header
if getattr(exc, 'wait', None):
headers['Retry-After'] = '%d' % exc.wait
if isinstance(exc.detail, (list, dict)):
data = exc.detail
else:
data = {'detail': exc.detail}
set_rollback()
return Response(data, status=exc.status_code, headers=headers)
# 只要是上面這些異常都做了處理
return None # 意味有些異常它沒有處理,就會交給Django自己處理
如何處理
因為dir有些異常它不做處理,Django處理的又不符合我們的標準,所以就要寫一個統(tǒng)一的異常類來替換掉它,把所有情況都處理,只要前端出異??吹降亩际枪潭ǖ臇|西。
如何寫:
重寫一個類,和它基本上差不多,配置的時候在 settings.py 里面全局配置
# app01_auth.py
from rest_framework.views import exception_handler
from rest_framework.response import Response
def app01_exception_handler(exc, context):
response = exception_handler(exc, context) # 原來的drf處理的我們也需要
# 兩種情況,一個是None,drf沒有處理,Django處理了,但是處理的不符合需求
# response對象,drf處理了我們需要的
if not response:
# 如果沒處理,那么我們自己處理
return Response(data={'status': 400, 'error': str(exc)}, status=400)
else:
# drf 處理了,那么取出它處理的信息,重新處理一下
return Response(data={'status': 400, 'error': response.data.get('detail')}, status=400)
然后再全局配置一下:settings.py
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'app01.app_auth.app01_exception_handler',
}
五、封裝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":'xiaoyang'},token='dsafsdfa',aa='dsafdsfdee')
return APIResponse(data={"name":'xiaoyang'})
return APIResponse(code='101',msg='錯誤',data={"name":'xiaoyang'},token='dsafsdfa',aa='dsafdsfdee',header={})
總結(jié)
到此這篇關(guān)于DRF過濾排序分頁異常處理的文章就介紹到這了,更多相關(guān)DRF過濾排序分頁內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:- Django實現(xiàn)drf搜索過濾和排序過濾