1. 程式人生 > 其它 >2個檢視基類,5個檢視擴充套件類,9個檢視子類,檢視集,drf自動生成路由

2個檢視基類,5個檢視擴充套件類,9個檢視子類,檢視集,drf自動生成路由

兩個檢視基類

APIView


GenericAPIView

# 匯入
from rest_framework.generics import GenericAPIView


類GenericView 繼承了APIView,

class GenericAPIView(views.APIView):
# 這裡面定義了兩個引數
queryset = None
serializer_class = None

# 記住3個方法
def get_queryset(self) # 獲取所有資料,查詢所有需要用到
def get_object(self): # 查詢單個物件,需要用到

def get_serializer(self, *args, **kwargs)
...
return serializer_class(*args, **kwargs)# 使用這個方法得到序列化類的物件,可以傳selif.get_serializer(instance,data,many)

def get_serializer_class(self)
...
return self.serializer_class
繼承了GenericAPIView類的檢視層類如下:
class BookGeneric(GenericAPIView):
queryset = Book.objects.all()
serializer_class = BookModelSerializers

# 查詢所有
def get(self,request,*args, **kwargs):
obj_list = self.get_queryset()
ser = self.get_serializer(obj_list, many=True)
return Response(ser.data)

def post(self,request,*args, **kwargs):
pass


class BookDetailGeneric(GenericAPIView):
queryset = Book.objects.all()
serializer_class = BookModelSerializers

# 修改某一個
def put(self, request, pk):
obj = self.get_object().filter(pk=pk).first()
ser = self.get_serializer(obj, data=request.data)
return Response(ser.data)

def get(self, request, pk):
pass

def delete(self, request,pk):
pass

五個檢視擴充套件類(沒有繼承其他類)

# 匯入5個檢視擴充套件類
# mixins.py
from rest_framework.mixins import CreateModelMixin,ListModelMixin,UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin
# 查詢所有,ListModelMixin,
# 新增 CreateModelMixin,

# 查詢單個 RetrieveModelMixin
# 更新某個 UpdateModelMixin
# 刪除某個 DestoryModelMixin
繼承GenericAPIView類 和檢視擴充套件類的檢視類
# 當有了上面5個檢視擴充套件類以後,就可以在我們自己寫的檢視類中自由組合的繼承他們,實現不同的介面功能
# 記得這裡寫了一個小作業,繼承GenericAPIView和一個自己寫的類,在新建檢視類中只配置那兩個引數,即可實現5個介面
# 如下,為一個查詢所有和新增的方法
class BookGenericList(GenericAPIView, ListModelMixin, CreateModelMixin):
queryset = Book.objects.all()
serializer_class = BookModelSerializers

def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)

def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)

9個檢視子類

現在,改寫一下上述檢視類,編寫檢視類繼承檢視子類實現同樣的功能,並且實現了程式碼少量書寫;

# 匯入檢視子類
# rest_framework.generics

from rest_framework.generics import ListAPIView,CreateAPIView,UpdateAPIView,DestroyAPIView,RetrieveAPIView
from rest_framework.generics import ListCreateAPIView,RetrieveUpdateAPIView,RetrieveDestroyAPIView
from rest_framework.generics import RetrieveUpdateDestroyAPIView

檢視類

# 此時我們只需要在自己寫的檢視類中繼承檢視子類ListCreateAPIView,就可以實現對資料的查詢所有,和增加一條
class BookListCreate(ListCreateAPIView):
queryset = Book.objects.all()
serializer_class = BookModelSerializers
# 刪除一條資料
class BookDestory(DestoryAPIView):
queryset = Book.objects.all()
serializer_class = BookModelSerializers

檢視集

可以看到檢視類繼承檢視子類之後的檢視類寫法變簡潔了,但是可以看見,上面兩個檢視類除了類名和繼承的類不一樣,下面的程式碼主體一樣。使用檢視集以後,能否將5個介面寫在一個檢視類中。請看下邊

# 匯入檢視集類
from rest_framework.viewsets import ModelViewSet,GenericViewSet,ViewSetMixin,ReadOnlyModelViewSet,ViewSet

路由

  # 使用檢視集的檢視類的url
path('bookviewset', views.BookViewSet.as_view({'get': 'list', 'post': 'create'})),
path('bookdetailviewset/<int:pk>', views.BookViewSet.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'}))

實現5個介面的檢視類

# 只繼承了一個檢視集ModelViewSet類就實現了5個介面的功能
class BookViewSet(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookModelSerializers

有點繞的東西

class ModelViewSet(mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet):

from rest_framework.generics
class GenericViewSet(ViewSetMixin, GenericAPIView):
pass

# 還是要抓住那個cls,以及cls例項化出來的物件
class ViewSetMixin:
@classonlymethod
def as_view(cls, actions=None, **initkwargs):
"""
Because of the way class based views create a closure around the
instantiated view, we need to totally reimplement `.as_view`,
and slightly modify the view function that is created and returned.
"""
# The name and description initkwargs may be explicitly overridden for
# certain route configurations. eg, names of extra actions.
cls.name = None
cls.description = None
cls.suffix = None
cls.detail = None
cls.basename = None
if not actions:
raise TypeError("The `actions` argument must be provided when "
"calling `.as_view()` on a ViewSet. For example "
"`.as_view({'get': 'list'})`")
for key in initkwargs:
if key in cls.http_method_names:
raise TypeError("You tried to pass in the %s method name as a "
"keyword argument to %s(). Don't do that."
% (key, cls.__name__))
if not hasattr(cls, key):
raise TypeError("%s() received an invalid keyword %r" % (
cls.__name__, key))

# name and suffix are mutually exclusive
if 'name' in initkwargs and 'suffix' in initkwargs:
raise TypeError("%s() received both `name` and `suffix`, which are "
"mutually exclusive arguments." % (cls.__name__))

def view(request, *args, **kwargs):
self = cls(**initkwargs)

if 'get' in actions and 'head' not in actions:
actions['head'] = actions['get']

# 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)

self.request = request
self.args = args
self.kwargs = kwargs

# And continue as usual
return self.dispatch(request, *args, **kwargs)

# We need to set these on the view function, so that breadcrumb
# generation can pick out these bits of information from a
# resolved URL.
view.cls = cls
view.initkwargs = initkwargs
view.actions = actions
return csrf_exempt(view)
...

drf自動生成路由

# 導自動生成路由的類
from rest_framework.routers import Simplerouter

# 例項化得到物件
router = Simplerouter()
# 註冊路由
router.register('路徑',對應的自己寫的檢視類)
# 路由地址的列表
router.urls
# 與路由層的urlpatterns 進行拼接
urlpatterns += router.urls

還有一種寫法
from django.urls import path,include

urlpatterns = [
path('', include(router.urls)),
# 也可以拼接路徑
path('api/v1/', include(router.urls)),
]