django rest framework mixins小結

引言
  本篇對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 {}

在這裏插入圖片描述

由上圖可以看出這個類的一個邏輯,其中,perform_create( )對serializer直接進行save保存,當在一些情境下,我們需要對perform_create( )進行重寫。
那麼我們現在可能有一個下面的需要:
  假設現在有一個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()

原文:https://blog.csdn.net/l_vip/article/details/79142105

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章