引言
本篇對drf中的mixins進行簡要的分析總結。
mixins在drf中主要配合viewset共同使用,實現http方法與mixins的相關類與方法進行關聯。關於viewset可以看我另外一篇部落格,這裡不過多介紹。
from rest_framework import viewsets
複製程式碼
在這個viewset中,只要有5類Minxin,他們與http方法對應如下:
下面,我們將逐個Mixins介紹!1. CreateModelMixin
# 原始碼
class CreateModelMixin(object):
"""
Create a model instance ==>建立一個例項
"""
def create(self, request, *args, **kwargs):
# 獲取相關serializer
serializer = self.get_serializer(data=request.data)
# 進行serializer的驗證
# raise_exception=True,一旦驗證不通過,不再往下執行,直接引發異常
serializer.is_valid(raise_exception=True)
# 呼叫perform_create()方法,儲存例項
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 {}
複製程式碼
假設現在有一個course課程model,裡面維持了一個數,記錄課程收藏數,還存在一個使用者收藏userfav的model(應當有一個外來鍵指向course),當一個使用者對課程進行收藏,理論上現在post進來的應該是userfav的instance,顯然,我們還需要對相應course的收藏數進行+1。
這個時候,我們就需要重寫perform_create( )方法!
def perform_create(self, serializer):
# 重寫save的邏輯
instance = serializer.save()
course = instance.course
course.fav_num += 1
course.save()
複製程式碼
顯然,這不是唯一的解決方法,我們還可以在seriliazer進行設定,我們還可以使用drf的訊號量進行解決!
2. ListModelMixin
# 原始碼
class ListModelMixin(object):
"""
List a queryset.==> 列表頁獲取
"""
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
# 這是一個分頁功能,如果在viewset中設定了pagination_class,那麼這裡就會起作用
# 獲取當前頁的queryset,如果不存在分頁,返回None
page = self.paginate_queryset(queryset)
if page is not None:
# 分頁不為空,那麼不能簡單的執行Response(serializer.data)
# 還需要將相關的page資訊序列化在進行響應
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)
複製程式碼
ListModelMixin一般用來獲取列表頁,大多數情況下比較簡單,不需要重寫相關的方法。
3. RetrieveModelMixin
# 原始碼
class RetrieveModelMixin(object):
"""
Retrieve a model instance.==> 獲取某一個物件的具體資訊
"""
def retrieve(self, request, *args, **kwargs):
# 一般訪問的url都為/obj/id/這種新式
# get_object()可以獲取到這個id的物件
# 注意在viewset中設定lookup_field獲取重寫get_object()方法可以指定id具體物件是什麼~!
instance = self.get_object()
serializer = self.get_serializer(instance)
return Response(serializer.data)
複製程式碼
對retrieve這個方法的重寫機率比較高,例如我們在增加點選數的時候,經常要對其進行一個重寫。
4. RetrieveModelMixin
# 原始碼
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)
def perform_update(self, serializer):
serializer.save()
def partial_update(self, request, *args, **kwargs):
kwargs['partial'] = True
return self.update(request, *args, **kwargs)
複製程式碼
RetrieveModelMixin的實現邏輯基本整合了Create以及Retrieve,先得到具體的例項,再對其進行驗證以及儲存,如果需要對更新這個邏輯進行自定義,那麼需要重寫perform_update( )方法,而儘量少去重寫update( )
5. 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()
複製程式碼
DestroyModelMixin的邏輯也相對比較簡單,我們取CreateModelMixin下面的例子,當我們取消收藏,那麼我們的DestroyModelMixin就發揮作用了。同理
def perform_create(self, serializer):
instance = serializer.save()
course = instance.course
if course.fav_num > 0:
course.fav_num -= 1
else:
course.fav_num = 0
course.save()
複製程式碼
小結
mixins相對比較好理解,本篇只是簡要的分析了原始碼的內容以及各個mixins的邏輯,最重要的還是學會去重寫它們相關的方法。
一般情況下,當我們在操作某一個model的時候,涉及到另外一個model中資料的修改,那麼就需要對這個mixins下執行save的邏輯的方法進行重寫。
CSDN:http://blog.csdn.net/l_vip/article/details/79142105