1. 程式人生 > 其它 >drf快速實現五個介面的方法

drf快速實現五個介面的方法

全域性規定請求格式編碼

 # 全域性規定請求格式編碼,settings檔案配置
REST_FRAMEWORK = {
    'DEFAULT_PARSER_CLASSES': [
        'rest_framework.parsers.JSONParser',  # 第一種編碼
        'rest_framework.parsers.FormParser',  # 第二種編碼
        'rest_framework.parsers.MultiPartParser'  # 第三種編碼
    ],
}

# 如果登出第一種編碼,也就相當於前端在新增或者修改的時候,提交的資料不能是json格式的編碼
# 如果登出第二種編碼,也就相當於前端在新增或者修改的時候,提交的資料不能是form-data格式的編碼
# 如果登出第三種編碼,也就相當於前端在新增或者修改的時候,提交的資料不能是url-encoded格式的編碼

# 同樣,如果只寫一種或者兩種,也就是說只接收前端傳過來的某一種或者某兩種編碼格式


# 區域性規定請求格式編碼,views檔案中的檢視類中寫
parser_classes = [FormParser]  # 括號內代表的是url-encoded編碼格式
parser_classes = [JSONParser]  # 括號內代表的是json編碼格式資料
parser_classes = [MultiPartParser]  # 代表的是form-data編碼格式資料

規定響應格式編碼

# 全域性規定響應格式編碼,settings檔案配置

REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': [
        'rest_framework.renderers.JSONRenderer',  # 第一種編碼格式
        'rest_framework.renderers.BrowsableAPIRenderer',  # 第二種
    ],}

# 如果登出第一種編碼,也就相當於後端提交資料(Response返回的時候)不能是json格式的資料返回,而是變成了其他格式的資料
# 如果登出第二種編碼,也就相當於後端提交資料(Response返回的時候)不能是瀏覽器格式的資料返回,而是變成了Json或者其他格式的資料
# 同理如果只寫一種,也就是指定那一種編碼格式返回到前端
renderer_classes = [JSONParser]
renderer_classes = [BrowsableAPIRenderer]

編碼格式規定的優先順序是

區域性 > 全域性(django配置檔案) > drf配置檔案

Response的引數

data  # 字典或者列表或者字串,可以將列表或者字典以json格式返回,字串的話返回到前端還是字串,返回到前端的資料放在了響應體中
status  # 狀態碼,可以直接寫數字,也可以調drf中的配置常量,相當於填寫的數
template_name  # 可以填一個html檔名字,會將該檔案返回到前端
headers  # 響應頭,可以放一個字典,會以鍵值對的形式放回給前端響應頭裡面
content_type  # 響應的編碼格式
exception  # 響應的異常資訊

檢視類的兩個檢視基類(APIView和GenericAPIView)

# 檢視基類APIView和檢視基類GenericAPIView的匯入方式
from rest_framework.generics import GenericAPIView
from rest_framework.views import APIView

我們發現在寫不同表模型類的介面的時候,都大差不差,程式碼明顯冗餘,如何解決這種問題,需要用到檢視類的兩個檢視基類
from rest_framework.generics import GenericAPIView
GenericAPIView類有兩個重要的類屬性
queryset = None
serializer_class = None

可以將這兩個類屬性寫在views類檢視函式裡面
queryset = models.Book.objects.all()  # 需要序列化的表的所有資料
serializer_class = 序列化器類  # 你要使用的序列化或者反序列化的類

1.雖然有queryset,但是我們一般用get_queryset方法,等同於queryset
 def get(self, request):
        book_queryset = self.queryset  # 物件呼叫類的屬性
        book_queryset = self.get_queryset()  # 物件呼叫類的方法
        book_queryset = models.Book.objects.all()
前面兩個等同於第三個,只不過前面兩個繼承的是GenericAPIView類
而第三個繼承的類是APIView


2.雖然有serializer_class類屬性,但是我們一般用get_serializer方法,等同於serializer_class
    def get(self, request):
        book = self.serializer_class(instance=book_queryset, many=True)
        book = self.get_serializer(instance=book_queryset, many=True)
        book = BookSerializers(instance=book_queryset, many=True)
前面兩個等同於第三個,只不過前面兩個繼承的是GenericAPIView類
而第三個繼承的類是APIView

3.獲取單條模型表的資料
    def get(self,request,pk):
        book_obj = models.Book.objects.filter(pk=pk).first()
        book_obj = self.get_objects()
4.Response返回的時候
正常返回,跟APIView一樣
5.總結
首先,路由方面還是不變,分倆個路由
path('books/', views.MyBooks.as_view()),
path('books/<int:pk>/', views.MyBook.as_view())
其次views.py檔案中的兩個CBV類也不變
class MyBooks   和   class MyBook
---最後這兩個檢視類MyBooks和MyBook都繼承了GenericAPIView類
---繼承GenericAPIView類
---兩個類屬性:
    queryset = None
    serializer_class = None
---三個方法:
    self.get_object()  # 獲取models表中的單條資料
    self.get_serializer(instance=None,data=None)
    self.get_queryset()  # 獲取要序列化的資料

五個檢視擴充套件類()

基於兩個檢視基類的進一步封裝,讓程式碼冗餘減少
繼承GenericAPIView類加五個檢視擴充套件類
五個試圖擴充套件類
from rest_framework.mixins import ListModelMixin          get
from rest_framework.mixins import RetrieveModelMixin      get
from rest_framework.mixins import UpdateModelMixin        put
from rest_framework.mixins import DestroyModelMixin       delete
from rest_framework.mixins import CreateModelMixin        post

首先我們需要在views的檢視類繼承GenericAPIView+任意一個五個檢視擴充套件類
1.如果加的是ListModelMixin檢視擴充套件類,那麼就相當於get獲取所有圖書資訊
class MyBooks(GenericAPIView,ListModelMixin):
    queryset = models.Book.objects.all()
    serializer_class = BookSerializers
    def get(self,request):
        return self.list(request)
2.如果想新增一個數據,需要加CreateModelMixin檢視擴充套件類
    def post(self,request):
        return self.create(request)
    需要注意的是它還有一個perform_create(self,serializer)方法,該方法是儲存校驗通過的資料,我們可以通過對他的重寫,從而達到當儲存多表的時候,實現實時的更新.serializer是校驗通過的資料serializer.save()
3.如果想獲取一個圖書資訊,需要用到RetrieveModelMixin試圖擴充套件類
    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)
4.如果想修改一個圖書資訊,需要用到UpdateModelMixin檢視擴充套件類
    def put(self,request,*args,**kwargs):
        return self.update(request,*args,**kwargs)
    
5.如果想刪除一個圖書資訊,需要用到DestroyModelMixin檢視擴充套件類
    def delete(self,request,*args,**kwargs):
        return self.destroy(request,*args,**kwargs)
需要注意的是它也寫了一個方法perform_destroy(self,instance)
我們可以重寫這個方法,在刪除之前做一點事情


6.總結,GenericAPIView類加五個檢視擴充套件類寫五個介面的步驟
首先,路由方面還是不變,分倆個路由
path('books/', views.MyBooks.as_view()),
path('books/<int:pk>/', views.MyBook.as_view())
其次views.py檔案中的兩個CBV類也不變
class MyBooks   和   class MyBook

# 最後是MyBooks類繼承了GenericAPIView加兩個檢視擴充套件類
# MyBook類繼承了GenericAPIView加三個檢視擴充套件類

九個檢視子類()

# 九個檢視子類的模組匯入如下
from rest_framework.generics import ListAPIView
from rest_framework.generics import CreateAPIView
from rest_framework.generics import ListCreateAPIView
from rest_framework.generics import RetrieveAPIView
from rest_framework.generics import UpdateAPIView
from rest_framework.generics import DestroyAPIView
from rest_framework.generics import RetrieveUpdateAPIView
from rest_framework.generics import RetrieveDestroyAPIView
from rest_framework.generics import RetrieveUpdateDestroyAPIView

1.檢視子類ListAPIView  # 等同於寫了一個獲取所有圖書的get請求方式的介面
檢視子類ListAPIView = 檢視基類GenericAPIView + 檢視擴充套件類ListModelMixin
class ListAPIView(mixins.ListModelMixin,
                  GenericAPIView):
ListAPIView檢視子類繼承了ListModelMixin檢視擴充套件類和GenericAPIView檢視基類
2.檢視子類CreateAPIView  # 等同於寫了一個新增一個圖書的post請求方式的介面
檢視子類CreateAPIView = 檢視基類GenericAPIView + 檢視擴充套件類CreateModelMixin
class CreateAPIView(mixins.CreateModelMixin,
                    GenericAPIView):

3.檢視子類RetrieveAPIView  # 等同於寫了一個查詢一本圖書的get請求方式的介面
檢視子類RetrieveAPIView = 檢視基類GenericAPIView + 檢視擴充套件類RetrieveModelMixin
class RetrieveAPIView(mixins.RetrieveModelMixin,
                      GenericAPIView):
4.檢視子類UpdateAPIView  # 等同於寫了一個修改一本圖書的put請求方式的介面
檢視子類UpdateAPIView = 檢視基類GenericAPIView + 檢視擴充套件類UpdateModelMixin
class UpdateAPIView(mixins.UpdateModelMixin,
                    GenericAPIView):
5.檢視子類DestroyAPIView  # 等同於寫了一個刪除一本圖書的delete請求方式的介面
檢視子類DestroyAPIView = 檢視基類GenericAPIView + 檢視擴充套件類DestroyModelMixin
class DestroyAPIView(mixins.DestroyModelMixin,
                     GenericAPIView):
    
6.檢視子類ListCreateAPIView  # 等同於寫了一個獲取所有圖書和新增一本圖書的get和post請求方式的兩個介面
檢視子類ListCreateAPIView = 檢視基類GenericAPIView + 檢視擴充套件類ListModelMixin + 檢視擴充套件類CreateModelMixin
class ListCreateAPIView(mixins.ListModelMixin,
                        mixins.CreateModelMixin,
                        GenericAPIView):
7.檢視子類RetrieveUpdateAPIView  # 等同於寫了一個獲取一本圖書和修改一本圖書的get和put請求方式的兩個介面
檢視子類RetrieveUpdateAPIView = 檢視基類GenericAPIView + 檢視擴充套件類RetrieveModelMixin + 檢視擴充套件類UpdateModelMixin
class RetrieveUpdateAPIView(mixins.RetrieveModelMixin,
                            mixins.UpdateModelMixin,
                            GenericAPIView):
8.檢視子類RetrieveDestroyAPIView  # 等同於寫了一個獲取一本圖書和刪除一本圖書的get和delete請求方式的兩個介面
檢視子類RetrieveDestroyAPIView = 檢視基類GenericAPIView + 檢視擴充套件類
RetrieveModelMixin + 檢視擴充套件類DestroyModelMixin
class RetrieveDestroyAPIView(mixins.RetrieveModelMixin,
                             mixins.DestroyModelMixin,
                             GenericAPIView):
9.檢視子類RetrieveUpdateDestroyAPIView  # 等同於寫了一個獲取一本圖書和修改一本圖書以及刪除一本圖書的get和put和delete請求方式的三個介面
檢視子類RetrieveUpdateDestroyAPIView = 檢視基類GenericAPIView + 檢視擴充套件類RetrieveModelMixin + 檢視擴充套件類UpdateModelMixin + 檢視擴充套件類DestroyModelMixin
class RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin,
                                   mixins.UpdateModelMixin,
                                   mixins.DestroyModelMixin,
                                   GenericAPIView):
10.總結
首先,路由方面還是不變,分倆個路由
path('books/', views.MyBooks.as_view()),
path('books/<int:pk>/', views.MyBook.as_view())
其次views.py檔案中的兩個CBV類也不變
class MyBooks   和   class MyBook
--只需要繼承你想要實現的介面類
--隨機組合,只要滿足五個介面就可以

檢視集

# 四個檢視集,需要匯入檢視集模組
from rest_framework.viewsets import ModelViewSet
from rest_framework.viewsets import ReadOnlyModelViewSet
from rest_framework.viewsets import ViewSet
from rest_framework.viewsets import GenericViewSet 
1.檢視集ModelViewSet  # 等同於寫了獲取所有,獲取單個,新增一個,修改一個,刪除一個的get,get,post,put,delete五個請求方式的介面
檢視集ModelViewSet = 檢視基類的子類GenericViewSet + ListModelMixin檢視擴充套件類
+ 檢視擴充套件類CreateModelMixin + 檢視擴充套件類RetrieveModelMixin 
+ 檢視擴充套件類UpdateModelMixin + 檢視擴充套件類DestroyModelMixin
class ModelViewSet(mixins.CreateModelMixin,
                   mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,
                   GenericViewSet):
2.檢視集ReadOnlyModelViewSet
class ReadOnlyModelViewSet(mixins.RetrieveModelMixin,
                           mixins.ListModelMixin,
                           GenericViewSet):
    pass
3.檢視集ViewSet  # 等同於APIView + ViewSetMixin
class ViewSet(ViewSetMixin, views.APIView):
    pass
4.GenericViewSet  # 等同於GenericAPIView + ViewSetMixin
class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
    pass
5.檢視集的父類GenericViewSet
class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
6.檢視集ModelViewSet的父類GenericViewSet的父類ViewSetMixin
所以說我們在as_view方法裡面填字典能夠對映,是該類實現的
路由匹配成功執行-->as_view方法,該方法是ViewSetMixin的as_view--->執行之後,他會將字典for迴圈解壓賦值成key,value的形式,其中通過getattr反射自己建立的類獲取value函式的記憶體地址,然後再通過setattr將key的記憶體地址替換成了value函式的記憶體地址--->執行value()-->後面的就跟View執行的流程大差不大了
# 所以說只要繼承了ViewSetMixin類,路由寫法就發生了變化,檢視類中方法可以隨意命名,只需要再路由中對映即可,也就是value值改變就可以

7.總結
首先,路由方面跟前面的大差不差,分倆個路由,唯一的區別是as_view裡面有引數,該引數是字典的形式,字典中的key代表請求方式,字典中的value代表的是該請求方式發出時候需要執行的函式。如{'get':'name','post':'egon'}
比如get請求方式發出的時候,會執行name函式,post請求發出的時候會執行egon函式。當然前提肯定是路由匹配成功,


# views.py檔案中的程式碼
from rest_framework.viewsets import ModelViewSet
class MyBooks(ModelViewSet):
    queryset = models.Book.objects.all()
    serializer_class = 序列化器類記憶體地址
    
# 路由urls.py中的程式碼
path('books/', views.MyBooks.as_view({'get':'list','post':'create'})),
path('books/<int:pk>/', views.MyBook.as_view({'get':'retrieve','put':'update','delete':'destroy'}))
需要知道每個關鍵的方法都在那個父類def list():  # 在ListModelMixin中寫了list方法    passdef create():  # 在CreateModelMixin中寫了create方法    passdef retrieve():  # 在RetrieveModelMixin中寫了retrieve方法    passdef update():  # 在UpdateModelMixin中寫了update方法    passdef destroy():  # 在DestroyModelMixin中寫了destroy方法    passdef perform_create(self,serializer):    pass    # 在CreateModelMixin中寫了perform_create方法    # 這個是post請求方式來的時候執行post函式中的create函式中的perform_create函式,該函式是專門建立新資料的函式def perform_destroy(self,instance):    pass    # 在DestroyModelMixin中寫了perform_destroy方法    # 這個是delete請求方式來的時候執行delete函式中的perform_destroy函式,該函式是專門處理刪除資料的函式
檢視集ModelViewSet-->GenericViewSet-->檢視基類GenericAPIView-->檢視基類APIView-->View-->object檢視集ModelViewSet-->GenericViewSet-->ViewSetMixin-->object檢視集ModelViewSet有6個父類