Welcome to kimi's blog

drf之视图层

视图组件和视图类的封装过程

视图组件介绍

APIView跟View区别

与View相比
1.传入到视图方法中的是REST_framework的Request对象,而不是Django的HttpRequeset对象;
2.视图方法可以返回REST_framework的Response对象
3.任何APIException异常都会被捕获到,并且处理成合适的响应信息
4.在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制


APIVIew
   类属性:
     renderer_classes   # 响应格式
     parser_classes     # 能够解析的请求格式
     authentication_classes   # 认证类
     throttle_classes    # 频率类
     permission_classes  # 权限类
   基于APIView+ModelSerializer+Resposne写5个接口

2个视图基类、5个视图扩展类以及9个视图子类

两个视图基类

APIView 和GenericAPIView

五个视图扩展类

CreateModelMixin,UpdateModelMixin,RetrieveModelMixin,DestroyModelMixin,ListModelMixin

九个视图子类

ListAPIView, CreateAPIView, ListCreateAPIView,RetrieveAPIView, UpdateAPIView, DestroyAPIView, RetrieveDestroyAPIView, RetrieveUpdateAPIView, RetrieveUpdateDestroyAPIView 

视图类,不需要额外继承GenericAPIView,只需要继承9个中其中某个,就会有某个或某几个接口

两个视图基类

基于APIView+ModelSerializer+Resposne写5个接口

路由

urlpatterns = [
    path('admin/', admin.site.urls),
    path('books/',views.BookAPIView.as_view()),
    path('books/<int:pk>/',views.BookDetailView.as_view())
]

视图类

from rest_framework.views import APIView, Response
from .models import Book
from .serializer import BookSerializer

class BookAPIView(APIView):
    # 获取序列化多条
    def get(self, request):
        books = Book.objects.all()
        ser = BookSerializer(instance=books, many=True)
        return Response(ser.data)

    # 新增图书
    def post(self, request):
        ser = BookSerializer(data=request.data)
        if ser.is_valid():
            ser.save()  # 书写create方法
   """1.想要的对象----ser序列化类的对象
      2.新增的对象----想要序列化成字典---》前提是序列化类中的create方法一定要返回新增的对象"""
            return Response({'code': 100, 'msg': '新增成功','result': ser.data}})
        else:
            return Response({'code': 100, 'msg': ser.errors})


class BookDetailView(APIView):
    # 获取单条
    def get(self, request, pk):
        book = Book.objects.filter(pk=pk).first()
        ser = BookSerializer(instance=book)
        return Response(ser.data)

    # 修改图书
    def put(self, request, pk):
        book = Book.objects.filter(pk=pk).first()
        ser = BookSerializer(data=request.data, instance=book)
        if ser.is_valid():
            ser.save()  # 书写update方法
            return Response({'code': 100, 'msg': '修改成功', 'result': ser.data})
        else:
            return Response({'code': 100, 'msg': ser.errors})

    # 删除
    def delete(self, request, pk):
        Book.objects.filter(pk=pk).delete()
        return Response({'code': 100, 'msg': '删除成功'})

序列化类

# ModelSerializer的使用
class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book  # 与book表关联
        fields = ['name', 'price', 'get_publish_detail', 'get_author_list', 'publish', 'authors']  # 序列化字段

        # 定制字段
        extra_kwargs = {
            'name': {'max_length': 8},
            'publish_detail': {'read_only': True},
            'author_list': {'read_only': True},
            'publish': {'write_only': True},
            'authors': {'write_only': True}
        }

继承GenericAPIView,编写五个接口

from rest_framework.response import Response
from rest_framework.generics import GenericAPIView

class BookAPIView(GenericAPIView):
    queryset = Book.objects.all()  #
    serializer_class = BookSerializer

    def get(self, request):
        # objs = Book.objects.all()
        # objs = self.queryset  # 可以拿到,但是不建议这么用,GenericAPIView提供了一个方法
        objs = self.get_queryset()
        """
        1.get_queryset()该方法的好处就是可以重写get_queryset()方法,后期扩展性比较好
        2.去序列化类,不要使用self.serializer_class ,而是使用get_serializer_class
        """
        # ser = BookSerializer(instance=objs, many=True)
        ser=self.get_serializer(instance=objs,many=True)
        return Response(ser.data)

    def post(self, request):
        ser = self.get_serializer(data=request.data)
        if ser.is_valid():
            ser.save()  # 书写create方法
            return Response({'code': 100, 'msg': '新增成功'})
        else:
            return Response({'code': 100, 'msg': ser.errors})

class BookDetailView(GenericAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    def get(self, request, pk):
        obj=self.get_object()  # 获取单条
        ser = self.get_serializer(instance=obj)
        return Response(ser.data)

    def put(self, request, pk):
        obj=self.get_object()
        ser = self.get_serializer(data=request.data, instance=obj)
        if ser.is_valid():
            ser.save()  # 书写update方法
            return Response({'code': 100, 'msg': '修改成功'})
        else:
            return Response({'code': 100, 'msg': ser.errors})

    def delete(self, request, pk):
        self.get_object().delete()
        return Response({'code': 100, 'msg': '删除成功'})

五个视图扩展类

基于GenericAPIView + 五个视图扩展类

  1. GenericAPIView的属性和方法
from rest_framework.generics import GenericAPIView

# 属性
1 queryset:要序列化或反序列化的表模型数据
2 serializer_class:使用的序列化类
3 lookup_field :查询单条的路由分组分出来的字段名
4 filter_backends:过滤类的配置(了解)
5 pagination_class:分页类的配置(了解)

# 方法
1 get_queryset :获取要序列化的对象
2 get_object :获取单个对象
3 get_serializer :获取序列化类  ,跟它差不多的get_serializer_class,一般重写它,不调用它
4 filter_queryset  :过滤有关系(了解)
  1. 基于GenericAPIView + 五个视图扩展类
    5个视图扩展类+GenericAPIView = 视图类

路由

urlpatterns = [
    path('admin/', admin.site.urls),
    path('books/', views.BookView.as_view()),
    path('books/<int:pk>/', views.BookDetailView.as_view()),
]

序列化类

# ModelSerializer的使用
class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book  # 与book表关联
        fields = ['name', 'price', 'get_publish_detail', 'get_author_list', 'publish', 'authors']  # 序列化字段

        # 定制字段
        extra_kwargs = {
            'name': {'max_length': 8},
            'publish_detail': {'read_only': True},
            'author_list': {'read_only': True},
            'publish': {'write_only': True},
            'authors': {'write_only': True}
        }

视图类

from rest_framework.mixins import CreateModelMixin,UpdateModelMixin,RetrieveModelMixin,DestroyModelMixin,ListModelMixin
class BookAPIView(GenericAPIView,ListModelMixin,CreateModelMixin):
    queryset = Book.objects.all()  #
    serializer_class = BookSerializer

    def get(self, request):
        return self.list(request)

    def post(self, request):
        return self.create(request)

class BookDetailView(GenericAPIView,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    # def get(self, request, pk):
    def get(self, request, *args,**kwargs):
        return self.retrieve(request,*args,**kwargs)

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

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

九个视图子类

封装成九个视图子类

这九个是视图子类,不需要额外继承GenericAPIView,只需要继承9个中其中某个,就会有某个或某几个接口,可以点击ListAPIView源码分析可知,该视图类有一个get方法,返回是一个list;该类继承的是GenericAPIView,父类有的方法,子类都可以使用,所以不再需要额外继承GenericAPIView

image
image

""" 基于上面再封装成九个视图类"""
from rest_framework.generics import ListAPIView, CreateAPIView, ListCreateAPIView
from rest_framework.generics import RetrieveAPIView, UpdateAPIView, DestroyAPIView, RetrieveDestroyAPIView, \
    RetrieveUpdateAPIView, RetrieveUpdateDestroyAPIView  # 没有DestroyUpdateAPIView方法,前提是没有查询删除不了

# 查询图书所有
class BookListView(ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

# 图书新增
class BookCreateView(CreateAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

# 图书修改
class BookUpdateView(UpdateAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

# 查询图书单条
class BookRetrieveView(RetrieveAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

# 删除图书
class BookDestroyView(DestroyAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

# 图书查询和删除功能
class BookRetrieveDestroyView(RetrieveDestroyAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

# 图书查询和修改功能
class BookRetrieveUpdateView(RetrieveUpdateAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

# 图书查询、修改和删除
# 查询图书单条
class BookRetrieveUpdateDestroyView(RetrieveUpdateDestroyAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
	
	
""" 总结:
ListAPIView + CreateAPIView  = ListCreateAPIView    给BookView继承的
RetrieveAPIView + DestroyAPIView = RetrieveDestroyAPIView  给BookDetailView视图提供的
RetrieveAPIView + UpdateAPIView  = RetrieveDestroyAPIView  给BookDetailView视图提供的
RetrieveAPIView + UpdateAPIView + DestroyAPIView = RetrieveUpdateDestroyAPIView   给BookDetailView视图提供的

发现Destroy 和Update 方法没有整合,

"""

最终通过继承可以写成下面两个类

""" 将上述的功能再整合一起"""
# 路由

urlpatterns = [
    path('books/', views.BookView.as_view()),
    path('books/<int:pk>/', views.BookView.as_view()),
]

# 视图

class BookAPIView(ListCreateAPIView):# 查询所有和新增一个
    queryset = Book.objects.all()
    serializer_class = BookSerializer

class BookDetailView(RetrieveUpdateDestroyAPIView): # 查询单条、更新和删除
    queryset = Book.objects.all()
    serializer_class = BookSerializer

视图类的封装过程

1. 基于APIView编写五个接口

class BookAPIView(APIView):
    def get(self, request):
        books = Book.objects.all()
        ser = BookSerializer(instance=books, many=True)
        return Response(ser.data)

    def post(self, request):
        ser = BookSerializer(data=request.data)
        if ser.is_valid():
            ser.save()  # 书写create方法
            return Response({'code': 100, 'msg': '新增成功'})
        else:
            return Response({'code': 100, 'msg': ser.errors})
        
class BookDetailView(APIView):
    def get(self, request, pk):
        book = Book.objects.filter(pk=pk).first()
        ser = BookSerializer(instance=book)
        return Response(ser.data)

    def put(self, request, pk):
        book = Book.objects.filter(pk=pk).first()
        ser = BookSerializer(data=request.data, instance=book)
        if ser.is_valid():
            ser.save()  # 书写update方法
            return Response({'code': 100, 'msg': '修改成功'})
        else:
            return Response({'code': 100, 'msg': ser.errors})

    def delete(self, request, pk):
        Book.objects.filter(pk=pk).delete()
        return Response({'code': 100, 'msg': '删除成功'})

2. 继承了GenericAPIView,编写五个接口

from rest_framework.response import Response
from rest_framework.generics import GenericAPIView

class BookAPIView(GenericAPIView):
    queryset = Book.objects.all()  #
    serializer_class = BookSerializer

    def get(self, request):
        # objs = Book.objects.all()
        # objs = self.queryset  # 可以拿到,但是不建议这么用,GenericAPIView提供了一个方法
        objs = self.get_queryset()
        """
        1.get_queryset()该方法的好处就是可以重写get_queryset()方法,后期扩展性比较好
        2.去序列化类,不要使用self.serializer_class ,而是使用get_serializer_class
        """
        # ser = BookSerializer(instance=objs, many=True)
        ser=self.get_serializer(instance=objs,many=True)
        return Response(ser.data)

    def post(self, request):
        ser = self.get_serializer(data=request.data)
        if ser.is_valid():
            ser.save()  # 书写create方法
            return Response({'code': 100, 'msg': '新增成功'})
        else:
            return Response({'code': 100, 'msg': ser.errors})

class BookDetailView(GenericAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    def get(self, request, pk):
        obj=self.get_object()  # 获取单条
        ser = self.get_serializer(instance=obj)
        return Response(ser.data)

    def put(self, request, pk):
        obj=self.get_object()
        ser = self.get_serializer(data=request.data, instance=obj)
        if ser.is_valid():
            ser.save()  # 书写update方法
            return Response({'code': 100, 'msg': '修改成功'})
        else:
            return Response({'code': 100, 'msg': ser.errors})

    def delete(self, request, pk):
        self.get_object().delete()
        return Response({'code': 100, 'msg': '删除成功'})

3. 基于GenericAPIView +五个视图扩展类 编写五个接口

""" 基于GenericAPIView+5个视图扩展类写接口
    都继承GenericAPIView,Publish和Book的区别是两个类属性
    在基础上封装5个视图扩展类编写5个接口,五个视图扩展类必须要配合GenericAPIView一起用才可以因为没有继承APIView及其子类
    CreateModelMixin:新增,之前封装写的是post方法--->而CreateModelMixin写了create方法,代码就是post的代码
    DestroyModelMixin:删除     destroy方法
    RetrieveModelMixin:查单条数据   retrieve方法
    ListModelMixin:查所有数据对象     list 方法
    UpdateModelMixin:更新      update方法
 """
from rest_framework.mixins import CreateModelMixin,UpdateModelMixin,RetrieveModelMixin,DestroyModelMixin,ListModelMixin
class BookAPIView(GenericAPIView,ListModelMixin,CreateModelMixin):
    queryset = Book.objects.all()  #
    serializer_class = BookSerializer

    def get(self, request):
        return self.list(request)

    def post(self, request):
        return self.create(request)

class BookDetailView(GenericAPIView,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    # def get(self, request, pk):
    def get(self, request, *args,**kwargs):
        return self.retrieve(request,*args,**kwargs)

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

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

4. 基于上述再封装9个视图类---->整合两个视图类

""" 基于上面再封装成九个视图类"""
from rest_framework.generics import ListAPIView, CreateAPIView, ListCreateAPIView
from rest_framework.generics import RetrieveAPIView, UpdateAPIView, DestroyAPIView, RetrieveDestroyAPIView, \
    RetrieveUpdateAPIView, RetrieveUpdateDestroyAPIView  # 没有DestroyUpdateAPIView方法,前提是没有查询删除不了

```python

# 路由

urlpatterns = [
    path('books/', views.BookView.as_view()),
    path('books/<int:pk>/', views.BookView.as_view()),
]

# 视图

class BookAPIView(ListCreateAPIView):# 查询所有和新增一个
    queryset = Book.objects.all()
    serializer_class = BookSerializer

class BookDetailView(RetrieveUpdateDestroyAPIView): # 查询单条、更新和删除
    queryset = Book.objects.all()
    serializer_class = BookSerializer

5. 基于ModelViewSet继承,编写五个类

要编写五个接口,对应写两个视图类,配置两条路由,通过观察发现连个视图类的代码几乎一模一样,我们借此引入了ModelViewSet类,继承它只需要编写一个视图类
改变了路由写法--->
path('books/', views.BookAPIView.as_view({'get': 'list', 'post': 'create'})), path('books/<int:pk>/',views.BookAPIView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'}))
在路由里面指名两个get方法分别对应的类具体方法,当是get请求,访问这个地址,就执行视图类的list方法或retrieve方法

# 视图类
from rest_framework.viewsets import ModelViewSet
class BookAPIView(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

# 路由
    path('books/', views.BookAPIView.as_view({'get': 'list', 'post': 'create'})),
    path('books/<int:pk>/', views.BookAPIView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'}))

解析源码

点开ModelViewSet源码可知,ModelViewSet封装了ListAPIViewCreateAPIViewRetrieveAPIViewUpdateAPIViewDestroyAPIView,直接继承ModelViewSet可以直接使用create、list、retrieve、destroy和update五种方法,但是我们查询单表和多条都是get的方法,所以需要在路由指名两个路由的get方法分别对应内置的方法( path('books/', views.BookAPIView.as_view({'get': 'list', 'post': 'create'}))

image

image

视图集

1.通过ModelView编写5个接口

# 视图类
from rest_framework.viewsets import ModelViewSet
class BookAPIView(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

# 路由
    path('books/', views.BookAPIView.as_view({'get': 'list', 'post': 'create'})),
    path('books/<int:pk>/', views.BookAPIView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'}))

2.通过ReadOnlyModelViewSet编写2个只读接口

ReadOnlyModelViewSet,该视图类只有只读方法,继承该方法,路由需要指名get对应的是查询所有还是查询单个,点开源码可知:

image

# 路由
urlpatterns = [
    path('books/', views.BookView.as_view({'get': 'list'})),
    path('books/<int:pk>/', views.BookView.as_view({'get': 'retrieve'})),
]

# 视图类
class BookView(ReadOnlyModelViewSet):  # 查询所有,新增一个
    queryset = Book.objects.all()
    serializer_class = BookSerializer

3.ViewSetMixin源码分析

image

image

源码分析:

ModelViewSet=CreateModelMixin+RetrieveModelMixin+UpdateModelMixin+DestroyModelMixin+ListModelMixin+GenericViewSet(没见过)
GenericViewSet=ViewSetMixin【没见过】+GenericAPIView【见过,两个视图基类的】
由上述可知,路由写法改变的原因源自ViewSetMixin

image

ViewSetMixin由注释可知,继承该类,路由的写法要遵循它要求的编写,路由配置就view.MyViewSet.as_view({'get': 'list', 'post': 'create'})

ViewSetMixin源码分析

1.当请求来了,路由匹配成功--->get请求,就会匹配成功books,就会执行views.BookView.as_view({'get': 'list', 'post': 'create'})()--->当执行as_view时,注意此时的as_view是ViewSetMixin的as_view

    @classonlymethod
    def as_view(cls, actions=None, **initkwargs):
        # 如果没有传actions,直接抛异常,路由写法变了后,as_view中不传字典,直接报错
        if not actions:
            raise TypeError("The `actions` argument must be provided when "
                            "calling `.as_view()` on a ViewSet. For example "
                            "`.as_view({'get': 'list'})`")
		# 。。。。其他代码不用看
        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            if 'get' in actions and 'head' not in actions:
                actions['head'] = actions['get']
            self.action_map = actions
            for method, action in actions.items():
                handler = getattr(self, action)
                setattr(self, method, handler)

            return self.dispatch(request, *args, **kwargs)
        # 去除了csrf校验
        return csrf_exempt(view)

 2.路由匹配成功执行 views.BookView.as_view({'get': 'list', 'post': 'create'})()--->它的本质是执行:ViewSetMixin中的as_view内的view()

 def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            if 'get' in actions and 'head' not in actions:
                actions['head'] = actions['get']
			# actions是传入的字典--->{'get':'list','post':'create'}
            self.action_map = actions
            # 第一次循环:method:get   action  :list
            # 第一次循环:method:post   action  : create
            for method, action in actions.items():
                # 反射:去视图类中反射 action对应的方法,action第一次是list,去视图集反射list方法
                # handler 就是视图类中的list方法
                handler = getattr(self, action)
                # 反射修改:把method:get 请求方法,handler:list
                # 将视图类的对象get方法,变成了list方法
                setattr(self, method, handler)

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

            return self.dispatch(request, *args, **kwargs)  # dispatch 是APIView的方法

总结

  1. 只要是继承ViewSetMixin的视图类,路由写法就变了(重写了as_view)
    路由变成了需要传入字典映射方法:{'get':'list','post':'create'}
  2. 只要传入actions,以后访问get就是访问list,访问post就是访问create
  3. 其他执行跟之前一样
  4. 以后视图类类中的方法名,可以任意命名,只要在路由中做好映射即可(重要)
  5. ViewSetMixin:不是视图类,y要配合视图类一起,它重写了as_view方法,导致路由写法变了,路由改变的本质就是通过传的actions做映射{'get':"xxx"}
  6. 继承APIView+自动生成路由---->ViewSet
class BookView(ViewSet,APIView): # ViewSet一定要写在前面
    pass
  1. 继承GenericAPIView+自动生成路由---->GenericViewSet
 class BookView(GenericViewSet,GenericAPIView): # GenericViewSet一定要写在前面
     pass

4.基于ViewSetMixin+APIView写视图类

由此可知,继承了ViewSetMixin,可扩展性就高了,可以通过指定方法,编写想要的方法,如下:通过将get=login,当请求来了,就优先执行视图类中的login方法

from rest_framework.viewsets import ViewSet,GenericViewSet,ViewSetMixin

class TestVAPIView(ViewSetMixin,APIView):
    def login(self,request):
        return Response('登录功能')

from rest_framework.viewsets包下的类


from rest_framework.viewsets下有几个类
ModelViewSet: 5个视图扩展类+ViewSetMixin+GenericAPIView
ReadOnlyModelViewSet: 2个视图扩展类+ ViewSetMixin + GenericAPIView  只读
ViewSetMixin: 魔法方法,该类重写as_view,继承它,路由写法变成了映射方法
ViewSet: ViewSetMixin + APIView
GenericViewSet :ViewSetMixin + GeneriCAPIView

注意:

  1. 以后想继承APIView,但想改变路由写法【视图类中方法任意命名】,要继承ViewSet
  2. 以后想继承GenericAPIView,但想改变路由写法【视图类中方法名任意命名】,要继承GenericViewSet
    img

视图层大总结

  1. 两个视图基类

    APIView、GenericAPIView
    
  2. 五个视图扩展类,不是视图类,必须配合GenercAPIView

    CreateModelMixin,UpdateModelMixin,RetrieveModelMixin,DestroyModelMixin,ListModelMixin
    
  3. 9个视图子类,是视图类,只需要继承某几个就可以实现功能

    ListAPIView, CreateAPIView, ListCreateAPIView,RetrieveAPIView, UpdateAPIView, DestroyAPIView, RetrieveDestroyAPIView, RetrieveUpdateAPIView, RetrieveUpdateDestroyAPIView 
    
    
  4. 视图集

    1. ModelViewSet

      # 视图类
      from rest_framework.viewsets import ModelViewSet
      class BookAPIView(ModelViewSet):
          queryset = Book.objects.all()
          serializer_class = BookSerializer
      
      # 路由
          path('books/', views.BookAPIView.as_view({'get': 'list', 'post': 'create'})),
          path('books/<int:pk>/', views.BookAPIView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'}))
      
    2. ReadOnlyModelViewSet

      # 路由
      urlpatterns = [
          path('books/', views.BookView.as_view({'get': 'list'})),
          path('books/<int:pk>/', views.BookView.as_view({'get': 'retrieve'})),
      ]
      
      # 视图类
      class BookView(ReadOnlyModelViewSet):  # 查询所有,新增一个
          queryset = Book.objects.all()
          serializer_class = BookSerializer
      
    3. ViewSetMixin

      不是视图类,是魔法方法,重写了as_view,

      # 路由
          path('test/',views.TestVAPIView.as_view({'get':'login'}))
      
      # 视图
      class TestVAPIView(ViewSetMixin,APIView):
      
          def login(self,request):
              return Response('登录功能')
      

      当请求来了,就优先执行视图类中的login方法,当请求方法多时,从左到右依次执行。

    4. ViewSet :ViewSetMixin + APIView

    5. GenericViewSet : ViewSetMixin + GenericAPIView

    eg:发送短信接口,视图类叫SendView ,方法叫send_sms,路由配置变了get --> send_sms

    # 视图
    class SendView(ViewSet):
        def send_sms(self,request):
            phone = request.query_params.get('phone')
            print('发送成功%s' % phone)
            return Response({'code':100,'msg':'发送成功'})
    
    # 路由
     path('send/',views.SendView.as_view({'get':'send_sms'}))
    
posted @ 2023-02-04 16:18  魔女宅急便  阅读(27)  评论(0)    收藏  举报
Title