django rest framework 檢視原始碼解析
檢視原始碼解析
1) CreateAPIView
提供 post 方法
繼承自: GenericAPIView、CreateModelMixin
2)ListAPIView
提供 get 方法
繼承自:GenericAPIView、ListModelMixin
3)RetireveAPIView
提供 get 方法
繼承自: GenericAPIView、RetrieveModelMixin
4)DestoryAPIView
提供 delete 方法
繼承自:GenericAPIView、DestoryModelMixin
5)UpdateAPIView
提供 put 和 patch 方法
繼承自:GenericAPIView、UpdateModelMixin
6)RetrieveUpdateAPIView
提供 get、put、patch方法
繼承自: GenericAPIView、RetrieveModelMixin、UpdateModelMixin
7)RetrieveUpdateDestoryAPIView
提供 get、put、patch、delete方法
繼承自:GenericAPIView、RetrieveModelMixin、UpdateModelMixin、DestoryModelMixin
下面就一個個來介紹:
Mixins的五個類:
首先點開ModelViewSet類:
class ModelViewSet(mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet):
點進第一個類中:
CreateModelMixin:
class CreateModelMixin(object):
"""
Create a model instance.
"""
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def perform_create(self, serializer):
serializer.save()
def get_success_headers(self, data):
try:
return {'Location': str(data[api_settings.URL_FIELD_NAME])}
except (TypeError, KeyError):
return {}
這是CreateModelMixin類下的原始碼,首先通過request獲取請求得到的資訊傳給引數serializer,對它進行使用者Token驗證,如果使用者通過,將其儲存並且通過return {‘Location’: str(data[api_settings.URL_FIELD_NAME])}儲存一個臨時頭部資料,最後將序列化的資料,響應狀態碼(201 Created:請求已經被實現)、頭部一併返回即可。
另外補充,get_serializer方法是繼承自GenericAPIView類的序列化資料。
RetrieveModelMixin:
class RetrieveModelMixin(object):
"""
Retrieve a model instance.
"""
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance)
return Response(serializer.data)
這是RetrieveModelMixin下的原始碼,首先同樣get_object和get_serializer是繼承自GenericAPIView類中的方法,這裡需要注意一下get_object的這條語句:
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
因為這個函式後面部分都是對lookup_url_kwarg這個引數進行處理,而給這個引數賦值的兩個,前者在最前面的初始引數是None,所以我們又跳到後者lookup_field,發現它的預設值是"pk",所以這也是為什麼我們之前只要是精確查詢路由部分正則後的引數都設為pk的原因。
def get_object(self):
"""
Returns the object the view is displaying.
You may want to override this if you need to provide non-standard
queryset lookups. Eg if objects are referenced using multiple
keyword arguments in the url conf.
"""
queryset = self.filter_queryset(self.get_queryset())
# Perform the lookup filtering.
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
assert lookup_url_kwarg in self.kwargs, (
'Expected view %s to be called with a URL keyword argument '
'named "%s". Fix your URL conf, or set the `.lookup_field` '
'attribute on the view correctly.' %
(self.__class__.__name__, lookup_url_kwarg)
)
filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
obj = get_object_or_404(queryset, **filter_kwargs)
# May raise a permission denied
self.check_object_permissions(self.request, obj)
return obj
總結:返回詳情檢視所需的模型類資料物件,預設使用lookup_field引數來過濾queryset。 在檢視中可以呼叫該方法獲取詳情資訊的模型類物件。若詳情訪問的模型類物件不存在,會返回404。該方法會預設使用APIView提供的check_object_permissions方法檢查當前物件是否有許可權被訪問。
- lookup_field 查詢單一資料庫物件時使用的條件欄位,預設為’pk’
- lookup_url_kwarg 查詢單一資料時URL中的引數關鍵字名稱,預設與look_field相同
UpdateModelMixin
class UpdateModelMixin(object):
"""
Update a model instance.
"""
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=partial)
serializer.is_valid(raise_exception=True)
self.perform_update(serializer)
if getattr(instance, '_prefetched_objects_cache', None):
# If 'prefetch_related' has been applied to a queryset, we need to
# forcibly invalidate the prefetch cache on the instance.
instance._prefetched_objects_cache = {}
return Response(serializer.data)
和前面的create類似,意思通過instance = self.get_object()獲取要修改的資料,然後get_serializer拿到序列化器、進行請求資料合法校驗、然後通過Token進行使用者驗證、然後將更新好的資料返回return Response(serializer.data)
DestroyModelMixin
class DestroyModelMixin(object):
"""
Destroy a model instance.
"""
def destroy(self, request, *args, **kwargs):
instance = self.get_object()
self.perform_destroy(instance)
return Response(status=status.HTTP_204_NO_CONTENT)
def perform_destroy(self, instance):
instance.delete()
通過pk(或者其他標識)獲取要刪除的資料,然後instance.delete()刪除,最後返回return Response(status=status.HTTP_204_NO_CONTENT)
HTTP 204(no content)表示響應執行成功,但沒有資料返回,瀏覽器不用重新整理。這個除了呼叫get_object方法獲取資料,其它都在類範圍內。
ListModelMixin
class ListModelMixin(object):
"""
List a queryset.
"""
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
queryset = self.filter_queryset(self.get_queryset()),ListModelMixin類list方法獲取了這個queryset,同樣該方法是在GenericAPIView類中,然後在判斷是否分頁,最後獲取self.get_serializer(queryset, many=True)序列化類,最後將序列化後的結果serializer.data作為返回return Response(serializer.data)返回即可。這裡就不再分析中間這段分頁的含義了,分頁也算一個元件,如果以後有時間,可以再開一貼分析一下,我們只要看懂前面和後面就行了。
五個類小結
其實我們發現上面這五個類進行的功能並不多,只是說幫我們省略了邏輯處理部分,還有解決了一些零零碎碎的小問題,那麼我們定義的路由,以及檢視部分定義的類,怎樣才能讓django識別到,並且既然是CBV,那麼就少不了as_view()方法,那麼它在哪,下面就讓我們進入GenericViewSet下
GenericViewSet
class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
"""
The GenericViewSet class does not provide any actions by default,
but does include the base set of generic view behavior, such as
the `get_object` and `get_queryset` methods.
"""
pass
直接進入繼承類。
ViewSetMixin
我們先進入ViewSetMixin模組類中,發現它類下的第一個便是as_view方法,然後再進一步可以看到view函式,我們此處需要的就是它:
def view(request, *args, **kwargs):
self = cls(**initkwargs)
# We also store the mapping of request methods to actions,
# so that we can later set the action attribute.
# eg. `self.action = 'list'` on an incoming GET request.
self.action_map = actions
# Bind methods to actions
# This is the bit that's different to a standard view
for method, action in actions.items():
handler = getattr(self, action)
setattr(self, method, handler)
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get
self.request = request
self.args = args
self.kwargs = kwargs
# And continue as usual
return self.dispatch(request, *args, **kwargs)
for method, action in actions.items():
handler = getattr(self, action)
setattr(self, method, handler)
這一段的意思是遍歷actions裡的資料,method接收的是字典的鍵,而action接收的是值,actions就是我們在url傳遞引數,然後通過getattr反射將action的值給handler,最後執行setattr,這個方法的意思是給物件的屬性賦值,若屬性不存在,先建立再賦值。也就是說將method方法裡的替換成handler。
APIView
之後找到我們想要定義的dispatch方法的回撥函式裡,這個是在APIView模組類中,並且算是重寫了dispatch方法,如果還想刨根揭底的話,就會發現它後面還有一個dispatch方法,是View模組下的,這個可以看上面我畫的流程圖。所以dispatch方法的返回值,就是view的返回值,view的返回值就是as_view的返回值,那麼我們整個原始碼邏輯就都通了。
相關文章
- django-rest-framework原始碼分析2—認證(Authentication)原始碼解析DjangoRESTFramework原始碼
- Django REST framework API 指南(5):檢視集DjangoRESTFrameworkAPI
- Django REST framework API 指南(4):通用檢視DjangoRESTFrameworkAPI
- Django REST framework API 指南(7):解析DjangoRESTFrameworkAPI
- 深度解析Django REST Framework 批量操作DjangoRESTFramework
- [Django REST framework - 檢視元件之檢視基類、檢視擴充套件類、檢視子類、檢視集]DjangoRESTFramework元件套件
- 二、django rest_framework原始碼之認證流程剖析DjangoRESTFramework原始碼
- Django-Rest-Framework 許可權管理原始碼淺析DjangoRESTFramework原始碼
- Django REST framework 分頁DjangoRESTFramework
- Django rest framework之ModelSerializDjangoRESTFramework
- django-rest-framework-原始碼解析004-三大驗證(認證/許可權/限流)DjangoRESTFramework原始碼
- Django REST framework API 指南(25):狀態碼DjangoRESTFrameworkAPI
- django rest framework serializers小結DjangoRESTFramework
- django rest_framework面經DjangoRESTFramework
- Django REST framework完全入門DjangoRESTFramework
- Django REST Framework Quickstart 專案DjangoRESTFrameworkUI
- Django框架rest_framework中APIView的as_view()原始碼解析、認證、許可權、頻率控制Django框架RESTFrameworkAPIView原始碼
- Django REST framework API 指南(21):SchemasDjangoRESTFrameworkAPI
- Token認證——Django Rest framework(1)DjangoRESTFramework
- Django REST Framework中的Serializer relationsDjangoRESTFramework
- Django REST framework API 指南(6):路由DjangoRESTFrameworkAPI路由
- Django REST framework API 指南(8):渲染DjangoRESTFrameworkAPI
- Django REST framework API 指南(27):SettingsDjangoRESTFrameworkAPI
- Django REST framework API 指南(15):限流DjangoRESTFrameworkAPI
- Django REST framework API 指南(17):分頁DjangoRESTFrameworkAPI
- Django REST framework API 指南(18):版本控制DjangoRESTFrameworkAPI
- Django REST framework API 指南(13):認證DjangoRESTFrameworkAPI
- 管理平臺模板 Django REST Framework +ElementUIDjangoRESTFrameworkUI
- View + django-rest-framework序列化ViewDjangoRESTFramework
- Django REST framework API 指南(23):返回 URLDjangoRESTFrameworkAPI
- Django REST framework API 指南(24):異常DjangoRESTFrameworkAPI
- Django REST framework API 指南(26):測試DjangoRESTFrameworkAPI
- Django REST framework API 指南(16):過濾DjangoRESTFrameworkAPI
- Django REST framework API 指南(12):驗證器DjangoRESTFrameworkAPI
- Django REST framework API 指南(14):許可權DjangoRESTFrameworkAPI
- Django REST framework API 指南(9):序列化DjangoRESTFrameworkAPI
- Django REST framework的請求與響應DjangoRESTFramework
- Django-rest-framework 是個什麼鬼?DjangoRESTFramework