django rest framework中對于APIView、GenericAPIView、ModelViewSet、mixins擴展類的分析,
APIView
示例
根據實際程式來分析:
urls.py
urlpatterns = [
re_path('users', UserAPIView.as_view())
]
views.py
class UserAPIView(APIView):
def get(self, request):
users = User.objects.filter().all()
ser = UserSerializer(instance=users, many=True)
return CommonResponse(status=status.HTTP_200_OK, data=https://www.cnblogs.com/wushengblog/p/ser.data)
原始碼分析
首先,UserAPIView繼承了APIView,而APIView繼承了View,
原生
View里面定義了允許的http訪問方式,
urls.py中,UserAPIView.as_view()這條陳述句其實執行的是APIView中的as_view()方法,而APIView中的as_view()方法執行父類View的as_view()方法,
APIView中的as_view()
View中的as_view()
其中關鍵的方法為dispatch方法,根據UserAPIView-->APIView-->View的繼承順序,該方法執行的是APIView中的dispatch方法,看下圖,
dispatch方法會獲取請求方式,判斷是否是http允許的請求方式,如果是的話,則分發執行UserAPIView中對應的同名方法,
其實我們也可以在UserAPIView中自定義dispatch方法,如下:
def dispatch(self, request, *args, **kwargs):
func = getattr(self,request.method.lower())
return func(request,*args,**kwargs)
總結:CBV基于反射實作根據請求方式不同,執行不同的方法,
View與APIView的執行流程
View:
as_view()是入口,得到view函式- 請求來了呼叫
view函式,內部呼叫dispatch函式完成請求分發 dispatch函式將請求方式映射為視圖類的同名方法,得到相應結果
APIView:
as_view()是入口,通過執行父類中的as_view方法得到view函式,然后在回傳view函式的時候免除csrf驗證,- 請求來了呼叫
view函式,內部呼叫(APIView類中的)dispatch方法完成請求分發, - 在
dispatch方法中,將會二次封裝request,完成三大驗證(認證、授權、節流),再將請求方式映射為視圖類的同名方法,完成請求的處理,
GenericAPIView
執行流程
首先看看GenericAPIView的原始碼,
可以看出,GenericAPIView繼承了APIView,然后還有幾個比較重要的類屬性,稍后用到再講,
再往下看它對外暴露的方法:
其實是比較少的,而且大多是get_xxx之類的方法,也就是說,它的as_view()、dispatch等方法,其實都是按照APIView的流程處理的,
重要方法
首先我們看get_queryset(),它的意思是批量查找資料庫的資料:
- 可以看到,queryset屬性必須進行賦值,按照繼承順序,我們直接在自己定義的視圖類中宣告queryset屬性并進行賦值,
- 在if判斷中,如果queryset是一個QuerySet物件,就獲取全部,得到一個QuerySetDict物件,否則原樣回傳,
QuerySetDict型別如下:
接下來看get_object(),它的意思是從資料庫中獲取單個物件:
filter_kwargs封裝查找條件,get_object_or_404負責在queryset中查找符合條件的物件(object),- 看到這里就發現了,默認查詢條件是用
pk,也就是說你的url中必須要用pk這個形參名進行分組捕獲,否則就需要宣告lookup_url_kwarg,如果url中的引數為name,那么lokup_url_kwarg="name",然后進行替換組建filter_kwargs,當然如果你的查詢條件不是用的pk,就需要修改lookup_field為欄位名,如我不是按照pk進行查詢,而是按照name,就修改lookup_field為name, - 同時也會檢查用戶是否有權限查看該物件,
check_object_permissions
主要的就是以上兩個,get_serializer()會呼叫get_serializer_class獲取序列化類,回傳序列化類的執行結果,
示例
class UserAPIView(GenericAPIView):
queryset = User.objects
serializer_class = UserSerializer
def get(self, request):
users = self.get_queryset()
ser = self.get_serializer(instance=users, many=True)
return CommonResponse(status=status.HTTP_200_OK, data=https://www.cnblogs.com/wushengblog/p/ser.data)
mixins擴展類
- 在
rest_framework.mixins中,有五個擴展類,分別是:ListModelMixin:該類主要負責查詢所有記錄RetrieveModelMixin:該類主要負責查詢單條記錄CreateModelMixin:該類主要負責創建記錄UpdateModelMixin:該類主要負責對記錄做更新操作DestroyModelMixin:該類主要負責洗掉記錄
- 這五個類都繼承于
object,是獨立的子類, - 針對
GenericAPIView更高級的封裝,配合GenericAPIView使用有奇效, - 會自動進行
return Response(),所以就不用我們再對回傳物件進行包裝了,
| 類 | 方法 | 描述 |
|---|---|---|
| ListModelMixin | list() | 查詢所有,并回傳Response物件 |
| RetrieveModelMixin | retrieve() | 查詢單條,并回傳Response物件 |
| CreateModelMixin | create() | 創建記錄,并回傳Response物件 |
| UpdateModelMixin | update() | 更新記錄,并回傳Response物件 |
| DestroyModelMixin | destroy() | 洗掉記錄,并回傳Response物件 |
示例
class UserAPIView(GenericAPIView, ListModelMixin):
queryset = User.objects
serializer_class = UserSerializer
def get(self, request):
return CommonResponse(status=status.HTTP_200_OK, data=https://www.cnblogs.com/wushengblog/p/self.list(request).data)
ModelViewSet
如果繼承所有的mixins類,則視圖類就會寫的非常冗長,可讀性較差,
同時,每次都要在視圖中return,那我們會考慮能不能簡化這步操作,
首先匯入ModelViewSet
from rest_framework.viewsets import ModelViewSet
查看它的原始碼:
再看GenericViewSet:
再看ViewSetMixin:
注釋的意思是說,它重寫了as_view()方法,系結了http方法與視圖函式中的方法,這讓它必須接收一個actions引數,actions引數設定為一個字典,
示例
urls.py
urlpatterns = [
re_path('users', UserAPIView.as_view(actions={"get": 'list'}))
]
views.py
class UserAPIView(ModelViewSet):
queryset = User.objects
serializer_class = UserSerializer
generics擴展類
至于generics擴展類,提供了以下幾個功能:
| 類 | 功能 |
|---|---|
| CreateAPIView | 創建記錄 |
| DestroyAPIView | 洗掉記錄 |
| UpdateAPIView | 更新單條記錄 |
| ListAPIView | 查詢所有記錄 |
| RetrieveAPIView | 查詢單條記錄 |
| ListCreateAPIView | 創建以及查詢所有記錄 |
| RetrieveUpdateAPIView | 更新以及查詢單條記錄 |
| RetrieveDestroyAPIView | 洗掉以及查詢單條記錄 |
| RetrieveUpdateDestroyAPIView | 洗掉、更新、查詢單條記錄 |
由此可見,generics中的擴展類都是結合了mixins擴展類和GenericAPIView,并且提供了標準的http方法同名方法,這些方法又都分別執行對應的mixins擴展類中的方法,這和我們mixins擴展類部分中的示例大體一致,
示例
urls.py
urlpatterns = [
re_path('users', UserAPIView.as_view(actions={"get": 'list'}))
]
Views.py
class UserAPIView(ViewSetMixin, ListAPIView):
queryset = User.objects
serializer_class = UserSerializer
注:UserAPIView的as_view方法要接收actions引數,而我們要使用的就是ViewSetMixin中重寫的as_view方法,因此為了不和ListAPIView中的as_view產生沖突,繼承時要把ViewSetMixin放在前面,
看完上面的內容,下面再看這張圖片,希望可以幫助梳理本篇文章的內容:
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/242207.html
標籤:Python


