drf4 视图与路由组件

APIView和View的区别

无论是View仍是APIView最开始调用的都是as_view()django

APIView继承了View, 而且执行了View中的as_view()方法,最后把view返回了,用csrf_exempt()方法包裹后去掉了csrf的认证。框架

 

在View中的as_view方法返回了view函数,而view函数执行了self.dispatch()方法,可是这里的dispatch方法应该是咱们APIView中的ide

 

去initialize_request中看下把什么赋值给了request,而且赋值给了self.request, 也就是咱们在视图中用的request.xxx究竟是什么~~函数

 

看到,这个方法返回的是Request这个类的实例对象~~咱们注意咱们看下这个Request类中的第一个参数request,是咱们走咱们django的时候的原来的requestpost

 

咱们看到了,这个Request类把原来的request赋值给了self._request, 也就是说之后_request是咱们老的request,新的request是咱们这个Request类url

 

咱们用了rest_framework框架之后,咱们的request是从新封装的Request类spa

request.query_params 存放的是咱们get请求的参数3d

request.data 存放的是咱们全部的数据,包括post请求的以及put,patch请求rest

相比原来的django的request,咱们如今的request更加精简,清晰了code

如今咱们知道了APIView和View的一些区别

 

视图的第一次封装

 

GenericAPIView 是对 APIView 的封装 
xxxMixin  是对处理的各类请求方法的封装
 
class BookView(APIView):

    def get(self, request):
        query_set = Book.objects.all()
        book_ser = BookSerializer(query_set, many=True)
        return Response(book_ser.data)

    def post(self, request):
        query_set = request.data
        book_ser = BookSerializer(data=query_set)
        if book_ser.is_valid():
            book_ser.save()
            return Response(book_ser.validated_data)
        else:
            return Response(book_ser.errors)


class BookEditView(APIView):

    def get(self, request, id):
        query_set = Book.objects.filter(id=id).first()
        book_ser = BookSerializer(query_set)
        return Response(book_ser.data)

    def patch(self, request, id):
        query_set = Book.objects.filter(id=id).first()
        book_ser = BookSerializer(query_set, data=request.data, partial=True)
        if book_ser.is_valid():
            book_ser.save()
            return Response(book_ser.validated_data)
        else:
            return Response(book_ser.errors)

    def delete(self, request, id):
        query_set = Book.objects.filter(id=id).first()
        if query_set:
            query_set.delete()
            return Response("")
        else:
            return Response("删除的书籍不存在")

APIView视图
APIView
from rest_framework.views import APIView
from rest_framework.viewsets import GenericViewSet
from rest_framework.response import Response
from .serializers import BookSerializer




class GenericAPIView(APIView):
    query_set = None
    serializer_class = None

    def get_queryset(self):
        return self.query_set

    def get_serializer(self, *args, **kwargs):
        return self.serializer_class(*args, **kwargs)


class ListModelMixin(object):
    def list(self, request):
        queryset = self.get_queryset()
        ret = self.get_serializer(queryset, many=True)
        return Response(ret.data)


class CreateModelMixin(object):
    def create(self, request):
        serializer = self.get_serializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        else:
            return Response(serializer.errors)


class RetrieveModelMixin(object):
    def retrieve(self, request, id):
        book_obj = self.get_queryset().filter(id=id).first()
        ret = self.get_serializer(book_obj)
        return Response(ret.data)


class UpdateModelMixin(object):
    def update(self, request, id):
        book_obj = self.get_queryset().filter(id=id).first()
        serializer = self.get_serializer(book_obj, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        else:
            return Response(serializer.errors)


class DestroyModelMixin(object):
    def destroy(self, request, id):
        book_obj = self.get_queryset().filter(id=id).first()
        book_obj.delete()
        return Response("")


class ListCreateAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):
    pass


class RetrieveUpdateDestroyAPIView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    pass


# class BookView(GenericAPIView, ListModelMixin, CreateModelMixin):
class BookView(ListCreateAPIView):
    query_set = Book.objects.all()      # 操做的表的对象
    serializer_class = BookSerializer   # 序列化的类

    def get(self, request):
        # book_obj = Book.objects.first()
        # ret = BookSerializer(book_obj)
        # book_list = Book.objects.all()
        # book_list = self.get_queryset()
        # ret = self.get_serializer(book_list, many=True)
        # return Response(ret.data)
        return self.list(request)

    def post(self, request):
        # print(request.data)
        # serializer = BookSerializer(data=request.data)
        # if serializer.is_valid():
        #     serializer.save()
        #     return Response(serializer.data)
        # else:
        #     return Response(serializer.errors)
        return self.create(request)


# class BookEditView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
class BookEditView(RetrieveUpdateDestroyAPIView):
    query_set = Book.objects.all()
    serializer_class = BookSerializer

    def get(self, request, id):
        # book_obj = Book.objects.filter(id=id).first()
        # ret = BookSerializer(book_obj)
        # return Response(ret.data)
        return self.retrieve(request, id)

    def put(self, request, id):
        # book_obj = Book.objects.filter(id=id).first()
        # serializer = BookSerializer(book_obj, data=request.data, partial=True)
        # if serializer.is_valid():
        #     serializer.save()
        #     return Response(serializer.data)
        # else:
        #     return Response(serializer.errors)
        return self.update(request, id)

    def delete(self, request, id):
        # book_obj = Book.objects.filter(id=id).first()
        # book_obj.delete()
        # return Response("")
        return self.destroy(request, id)
视图的第一次封装

 

 

视图的第二次封装

 

class ListCreateAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):
    pass

class RetrieveUpdateDestroyAPIView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    pass

class BookView(ListCreateAPIView):
    pass

class BookEditView(RetrieveUpdateDestroyAPIView):
    pass
# 上面咱们写的继承类太长了~~咱们再改改

class ListCreateAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):
    pass


class RetrieveUpdateDestroyAPIView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    pass


class BookView(ListCreateAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

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

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


class BookEditView(RetrieveUpdateDestroyAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

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

    def patch(self, request, id, *args, **kwargs):
        return self.update(request, id, *args, **kwargs)

    def delete(self, request, id, *args, **kwargs):
        return self.delete(request, id, *args, **kwargs)

第二次封装
第二次封装

视图的第三次封装

 

ViewSetMixin

actions这个默认参数其实就是咱们路由能够进行传参了

下面这个循环,能够看出,咱们要传的参数是一个字段~key应该是咱们的请求方式,value应该对应咱们处理的方法

这样咱们每一个视图就不用在写函数了,由于已经和内部实现的函数相对应了

由于是按照请求的方式不一样反回的结果,全部第二次有两个视图函数

 

如今指定一个视图函数

  # 视图类传参,不一样的请求对应不一样的方法
    path('list', BookModelViewSet.as_view({"get": "list", "post": "create"})),
    path('retrieve/<int:pk>', BookModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),

注意一点,用框架封装的视图,咱们url上的那个关键字参数要用pk,系统默认的

# class ViewSetMixin(object):
#     def as_view(self):
#         """
#         按照咱们参数指定的去匹配 对应的方法
#         get-->list
#         :return: 不用咱们去写,框架有
#         """

 

ViewSetMixin 请求分发方法的原理,将不一样的请求设置为不一样的方法

 

from rest_framework.viewsets import ViewSetMixin


# class BookView(ViewSetMixin, ListCreateAPIView, RetrieveUpdateDestroyAPIView):
#     queryset = Book.objects.all()
#     serializer_class = BookSerializer


# 若是咱们再定义一个类
class ModelViewSet(ViewSetMixin, ListCreateAPIView, RetrieveUpdateDestroyAPIView):
    pass


class BookView(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

第三次封装
第三次封装
from rest_framework.viewsets import ViewSetMixin

class ModelViewSet(ViewSetMixin, GenericAPIView, ListModelMixin, CreateModelMixin, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
    pass

# from rest_framework.viewsets import ModelViewSet
#  框架内部已经实现了的,能够直接导入
#
class BookModelViewSet(ModelViewSet):
    
    query_set = Book.objects.all() 本身封装的query_set
  # queryset = Book.objects.all() # 框架的是queryset
serializer_class = BookSerializer
 
 
 
 
 
 
 
 
from rest_framework import views     # APIView
from rest_framework import generics # GenericAPIView, 组合类
from rest_framework import mixins #混合继承类
from rest_framework import viewsets # ViewSetMixin 分发请求的类

 

咱们如今的视图就只要写两行就能够了

 

 

image

用框架的时

路由为

 path('retrieve/<int:pk>', BookModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),

 

前面本身定义的是id,用框架时注意修改过来

 path('retrieve/<int:id>', BookModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),

 

 # 视图类传参.只有业务需求匹配性很强才用。一般状况下不这么用容易暴露接口
 # path('list', BookModelViewSet.as_view({"get": "list", "post": "create"})),
 # path('retrieve/<int:id>', BookModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),

继承顺序

 

DRF的路由

 

from django.urls import path, include
from .views import BookView, BookEditView, BookModelViewSet
from rest_framework.routers import DefaultRouter


router = DefaultRouter()

router.register(r"", BookModelViewSet)  # 不能 加$ r"$"


urlpatterns = [
    # path('list', BookView.as_view()),
    # path('retrieve/<int:id>', BookEditView.as_view()),


    # 视图类传参.只有业务需求匹配性很强才用。一般状况下不这么用容易暴露接口
    # path('list', BookModelViewSet.as_view({"get": "list", "post": "create"})),
    # path('retrieve/<int:id>', BookModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),

]


urlpatterns += router.urls

DefaultRouter
DRF的路由

经过框架咱们能够把路由视图都变的很是简单,可是须要自定制的时候仍是须要咱们本身用APIView写

当不须要那么多路由的时候,也不要用这种路由注册

总之,一切按照业务须要去用

相关文章
相关标签/搜索