(资料图)
5个视图扩展类# 写5个类(不叫视图类 视图拓展类 需要配合GenericAPIView一起用) 每个类有一个方法 以后想写哪个接口 就继承哪个类即可from rest_framework.response import Response####自己封装的5个视图拓展类class ListModelMixin: def list(self,request): qs = self.get_queryset() ser = self.get_serializer(qs,many=True) return Response({"code":100,"msg":"成功","result":ser.data})class CreateModelMinxin: def create(self,request): ser = self.get_serializer(data=request.data) if ser.is_valid(): ser.save() return Response({"code":100,"msg":"成功"}) else: return Response({"code":100,"msg":"失败"})class RetrieveModelMixin: def retrieve(self,request,*args,**kwargs): qs = self.get_object() ser = self.get_serializer(qs) return Response({"code":100,"msg":"成功","result":ser.data})class UpdateModelMixin: def update(self,request,*args,**kwargs): qs = self.get_object() ser = self.get_serializer(qs,data=request.data) if ser.is_valid(): ser.save() return Response({"code":100,"msg":"成功"}) else: return Response({"code": 100, "msg": "失败"})class DestroyModelMixin: def destroy(self,request,*args,**kwargs): qs = self.get_object() qs.delete() return Response({"code":100,"msg":"成功"}) #### drf封装好的from .models import Bookfrom .serializer import BookSerializerfrom rest_framework.response import Responsefrom rest_framework.generics import GenericAPIViewfrom rest_framework.mixins import ListModelMixin,CreateModelMinxin,UpdateModelMinxin,DestroyModelMixin,RetrieveModelMixinclass BookView(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.object.all() serializer_class = BookSerializer 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)
# 5个视图扩展类(不是视图类)---》必须配合GenericAPIView及其子类使用---》不能配合APIView使用# 5个视图扩展类 每一个类中只有一个方法 完成5个接口中的其中一个 想写多个接口 就要继承多个
9个视图子类"""基于视图子类写接口 9个视图子类--->视图类"""from rest_framework.generics import ListAPIView,CreateAPIView,RetrieveAPIView,UpdateAPIView,DestroyAPIViewfrom rest_framework.generics import ListCreateAPIViewfrom rest_framework.generics import RetrieveUpdateDestroyAPIViewfrom rest_framework.generics import RetrieveUpdateAPIViewfrom rest_framework.generics import RetrieveDestroyAPIView# from rest_framework.generics import UpdateDestroyAPIView # 这个没有# ModelViewSet:继承它后 只需要在视图类中写两行 queryset = Book.objects.all() serializer_class = BookSerializer 配置路由,5个接口都有了 path("books/", BookView.as_view({"get": "list", "post": "create"})), path("books//", BookView.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})), ######def list(self, request, *args, **kwargs): res = super().list(request,*args,**kwargs) return Response({"code": 100, "msg": "成功", "data": res.data})可以重写父类中的方法 但是一定不能用self. 必须使用super() 否则会递归 # ModelViewSet 源码分析继承了: mixins.CreateModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, mixins.ListModelMixin, GenericViewSet ViewSetMixin : 重写看as_view方法 GenericAPIView 只要继承了ModelViewSet,路由写法变了,谁控制它变的:ViewSetMixin # ViewSetMixin 如何控制路由写法变了?(源码如下)BookView.as_view 是在执行ViewSetMixin的as_view @classonlymethod def as_view(cls,actions=None,**initkwargs): # 我们传入的 actions={"get":"list","post":"create"} def view(request,*args,**kwargs): self = cls(**initkwargs) for method,action in actions.items(): # method:get # action:list # 通过反射 self是BookView的对象 去BookView对象中反射list hander = getattr(self,action) # 通过反射:setattr(BookView的对象,"get",list方法) setattr(self,method,handler) # APIView的dispatch return self.dispatch(request,*args,**kwargs) return csrf_exempt(view) # 总结:"""1.只要继承了ViewSetMixin及其子类,路由写法就变了,必须传actions参数2.变成映射关系了:path("books/", BookView.as_view({"get": "list", "post": "create"})),3.以后 只要是books路由匹配成功的get请求 就会执行视图类BookView的list方法4.用户视图类中的方法名 可以随意命名5.这个类 必须配合视图类使用(APIView,GenericAPIView,9个视图子类),必须放在视图类之前"""
视图集# 两个视图基类APIView GenericAPIView# 5个视图扩展类(不是视图类 需要配合GenericAPIView及其子类使用)# 9个视图子类# 视图集:ModelViewSet:5个接口的 ReadOnlyModelViewSet:两个接口 list和retrieve ViewSetMixin:魔法 不能单独使用,必须配合视图类用 路由写法变了 ViewSet:ViewSetMixin + APIView 以后想继承APIView 但是想路由写法变化 视图类中方法可以任意命名 GenericViewSet:ViewSetMixin + GenericAPIView 以后想继承GenericAPIView 但是想路由写法变化 视图类中方法可以任意命名
drf之路由# 路由的写法有多种原始写法 映射的写法:path("books/",BookView.as_view({"get":"list","post":"create"})) 自动生成路由 # 自动生成路由必须要继承ViewSetMixin及其子类的视图类,才能用 继承了 5个视图扩展类+ViewSetMixin的视图类,能自动生成路由(ModelViewSet)跟咱们写的这个是一样的 path("books/", BookView.as_view({"get": "list", "post": "create"})), path("books//", BookView.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})) """第一步 导入一个路由类"""from rest_framework.routers import SimpleRouter"""第二步 实例化得到对象"""router = SimpleRouter()"""第三步 注册路由(视图类) 第一个参数是前缀 第二个参数是视图类 第三个参数是别名"""router.register("books",BookView,"books")# http://127.0.0.1:8000/api/v1/books/books/# 第一个books是注册路由时的前缀 第二个books是action装饰器的url_path参数"""第四部 加入到路由中"""# 4.1 方式一# urlpatterns += router.urls# 4.2 方式二# 使用include path("api/v1/", include(router.urls)), # 自动生成路由1.继承了 5个视图扩展类 + ViewSetMixin的视图类 能自动生成路由 (get:list,get:retrieve..) 2. 我们自己命名的: 方法名:login send_sms,需要使用装饰器来做 # 视图类 class SMSView(ViewSet): @action(methods=["GET"], detail=False, url_path="lqz", url_name="lqz") def lqz(self, request): return Response("你好") # 路由 router.register("lqz",SMSView,"lqz") # 路径是:http://127.0.0.1:8000/api/v1/lqz/lqz/ 第一个是前缀第二个是url_path的参数 如果没有就是函数名 3.action装饰器的参数 methods:请求方式 是以列表的形式 detail:一个True,一个False,用True,表示生成详情的路径 # True books/1/方法名/ # False,books/方法名/ url_path:路径名字 需要加上前面的路径一起 如果不给这个参数 则默认以函数名作为路径名 url_name:反向解析使用的名字(用的不多) # 路由类,有两个,用法完全一致,区别是DefaultRouter生成的路径多 SimpleRouter :用的最多 DefaultRouter # DefaultRouter与SimpleRouter的区别是,DefaultRouter会多附带一个默认的API根视图,返回一个包含所有列表视图的超链接响应数据(提示你可以访问哪些路径)。
关键词: