在from rest_framework import viewsets
這個(gè)viewset中片任,只要有5類Minxin船万,他們與http方法對應(yīng)如下:
- CreateModelMixin
# 源碼
class CreateModelMixin(object):
"""
Create a model instance ==>創(chuàng)建一個(gè)實(shí)例
"""
def create(self, request, *args, **kwargs):
# 獲取相關(guān)serializer
serializer = self.get_serializer(data=request.data)
# 進(jìn)行serializer的驗(yàn)證
# raise_exception=True,一旦驗(yàn)證不通過崖堤,不再往下執(zhí)行吗氏,直接引發(fā)異常
serializer.is_valid(raise_exception=True)
# 調(diào)用perform_create()方法幅垮,保存實(shí)例
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):
# 保存實(shí)例
serializer.save()
def get_success_headers(self, data):
try:
return {'Location': str(data[api_settings.URL_FIELD_NAME])}
except (TypeError, KeyError):
return {}
由上圖可以看出這個(gè)類的一個(gè)邏輯乌昔,其中隙疚,perform_create( )對serializer直接進(jìn)行save保存,當(dāng)在一些情境下磕道,我們需要對perform_create( )進(jìn)行重寫供屉。
那么我們現(xiàn)在可能有一個(gè)下面的需要:
??假設(shè)現(xiàn)在有一個(gè)course課程model,里面維持了一個(gè)數(shù)捅厂,記錄課程收藏?cái)?shù)贯卦,還存在一個(gè)用戶收藏userfav的model(應(yīng)當(dāng)有一個(gè)外鍵指向course),當(dāng)一個(gè)用戶對課程進(jìn)行收藏焙贷,理論上現(xiàn)在post進(jìn)來的應(yīng)該是userfav的instance撵割,顯然,我們還需要對相應(yīng)course的收藏?cái)?shù)進(jìn)行+1辙芍。
??這個(gè)時(shí)候啡彬,我們就需要重寫perform_create( )方法!
def perform_create(self, serializer):
# 重寫save的邏輯
instance = serializer.save()
course = instance.course
course.fav_num += 1
course.save()
- ListModelMixin
# 源碼
class RetrieveModelMixin(object):
"""
Retrieve a model instance.==> 獲取某一個(gè)對象的具體信息
"""
def retrieve(self, request, *args, **kwargs):
# 一般訪問的url都為/obj/id/這種新式
# get_object()可以獲取到這個(gè)id的對象
# 注意在viewset中設(shè)置lookup_field獲取重寫get_object()方法可以指定id具體對象是什么~故硅!
instance = self.get_object()
serializer = self.get_serializer(instance)
return Response(serializer.data)
對retrieve這個(gè)方法的重寫幾率比較高庶灿,例如我們在增加點(diǎn)擊數(shù)的時(shí)候,經(jīng)常要對其進(jìn)行一個(gè)重寫吃衅。
- RetrieveModelMixin
# 源碼
class UpdateModelMixin(object):
"""
Update a model instance.==> 更新某個(gè)具體對象的內(nèi)容
"""
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的實(shí)現(xiàn)邏輯基本整合了Create以及Retrieve往踢,先得到具體的實(shí)例,再對其進(jìn)行驗(yàn)證以及保存徘层,如果需要對更新這個(gè)邏輯進(jìn)行自定義峻呕,那么需要重寫perform_update( )方法,而盡量少去重寫update( )
- 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的邏輯也相對比較簡單趣效,我們?nèi)reateModelMixin下面的例子瘦癌,當(dāng)我們?nèi)∠詹兀敲次覀兊腄estroyModelMixin就發(fā)揮作用了跷敬。同理:
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()
一般情況下讯私,當(dāng)我們在操作某一個(gè)model的時(shí)候,涉及到另外一個(gè)model中數(shù)據(jù)的修改,那么就需要對這個(gè)mixins下執(zhí)行save的邏輯的方法進(jìn)行重寫斤寇。