9个视图子类
from rest_framework.generics import ListAPIView, CreateAPIView, ListCreateAPIView from rest_framework.generics import RetrieveAPIView, DestroyAPIView, UpdateAPIView from rest_framework.generics import RetrieveUpdateDestroyAPIView, RetrieveDestroyAPIView, RetrieveUpdateAPIView
以后想写5个接口中的某一个或某几个或所有,只需要选择继承不同的类即可,类中只需要配置两个类属性:
queryset = Publish.objects.all() serializer_class = PublishSerializer
视图类
#1 想写 publish: 查询所有,查询单条,修改一条,新增一条,删除一条的接口 class PublishView(ListCreateAPIView): queryset = Publish.objects.all() serializer_class = PublishSerializer class PublishDetailView(RetrieveUpdateDestroyAPIView): queryset = Publish.objects.all() serializer_class = PublishSerializer #2 想写 publish: 查询单条,新增一条,的接口--->使用9个视图子类编写 class PublishView(CreateAPIView): queryset = Publish.objects.all() serializer_class = PublishSerializer class PublishDetailView(RetrieveAPIView): queryset = Publish.objects.all() serializer_class = PublishSerializer #3 想写 publish: 查询单条,新增一条,的接口--->使用5个视图扩展类+GenericAPIView class PublishView(GenericAPIView,CreateModelMixin): queryset = Publish.objects.all() serializer_class = PublishSerializer
def post(self,request,*args,**kwargs): return self.create(request,*args,**kwargs)
class PublishDetailView(GenericAPIView,RetrieveModelMixin): queryset = Publish.objects.all() serializer_class = PublishSerializer
def get(self,request,*args,**kwargs): return self.retrieve(request,*args,**kwargs)
路由配置
path('publish/', PublishView.as_view()), path('publish/<int:pk>', PublishView.as_view()),
视图集
ModelViewSet
# 视图类只要继承了ModelViewSet,路由写法改一下,5个接口就都有了 from rest_framework.viewsets import ModelViewSet class PublishView(ModelViewSet): queryset = Publish.objects.all() serializer_class = PublishSerializer path('publish/', PublishView.as_view({'get':'list','post':'create'})), path('publish/<int:pk>', PublishView.as_view({'get':'retrieve','put':'update','delete':'destroy'})),
ModelViewSet源码分析
# 继承了5个试图扩展类,能够使用试图扩展类中的方法 mixins.CreateModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, mixins.ListModelMixin, # 有查询所有接口 -get--list----》拿到所有数据,序列化--返回 # 新增一条 -post---create---》之前咱们写的新增的代码一样的 # 为什么get 就变成了list # 为什么post 就变成了create # 继承了GenericViewSet类,
而这个类继承了ViewSetMixin类,这个类中重写了as_view方法,
只要将路由更改成类似
path('publish/', PublishView.as_view({'get':'list','post':'create'}))
的形式就可以映射出v值代表的方法
ViewSetMixin
# ViewSetMixin类 决定了以后路由写法变成了如下形式 path('publish/', PublishView.as_view({'get':'list','post':'create'})) path('publish/', PublishView.as_view({'get':'lqz'})) # 源码分析 class GenericViewSet(ViewSetMixin, generics.GenericAPIView):ViewSetMixin必须放前面--》保证执行的as_view是ViewSetMixin的 # 请求来了,路由匹配成功---》执行ViewSetMixin的as_view内的view(request) def view(request, *args, **kwargs): self = cls(**initkwargs) # 类实例化得到对象--》self是谁的对象?PublishView self.action_map = actions # {'get':'list','post':'create'} # method:get # action: list for method, action in actions.items(): # list 方法 handler = getattr(self, action) #PublishView对象中反射list,拿到了 # 反射设置值 #setattr(PublishView视图类的对象,get,list 方法) # PublishView视图类的对象中就会有一个get方法,就是list setattr(self, method, handler) return self.dispatch(request, *args, **kwargs) ''' 总结: -路由中这样配置:PublishView.as_view({'get':'list','post':'create'}) -以后get请求过来,本质执行的就是视图类中的list方法 '''
以后试图类中的方法名可以随意命名,只要路由做好映射
前提条件:
继承的类是:只要继承ViewSetMixin ,就能视图类中方法任意命名,路由写法变化
# 路由写法变成类似这种的 PublishView.as_view({'get':'list','post':'create'})
ReadOnlyModelViewSet
以后写的接口,如果只需要有 查询所有 和 查询单条 ,就继承它
视图层中类的总结
# 1. 两个视图基类 APIView和GenericAPIView APIView的执行流程:包装了新的request,处理了csrf,执行了3大认证(字段自己、局部钩子、全局钩子)、处理了全局异常 GenericAPIView:要做序列化,要跟数据库打交道,就直接继承它即可 重要类属性 queryset serializer_class 重要方法 get_queryset get_object get_serializer # 2. 5个视图扩展类(不是视图类),需要GenericAPIView才能用 # 快速使用5个接口 # 使用某几个接口:查询单条、新增一条的接口===》使用5个视图扩展类+GenericAPIView class PublishView(GenericAPIView,CreateModelMixin) queryset=Publish.objects.all() serializer_class=序列化类 def post(self,request) return self.create(request) class PublishDetailView(GenericAPIView,RetrieveModelMixin) queryset=Publish.objects.all() serializer_class=序列化类 def get(self,request) return self.retrieve(request) # 3. 9个视图子类(继承GenericAPIView + 5个视图扩展类的组合) ListAPIView, CreateAPIView ListCreateAPIView RetrieveAPIView, DestroyAPIView, UpdateAPIView RetrieveUpdateDestroyAPIView, RetrieveDestroyAPIView, RetrieveUpdateAPIView # 视图集 ModelViewSet: 继承:ViewSetMixin + GenericAPIView + 5个视图子类 或继承:GenericAPIView + 5个视图扩展类 ViewSetMixin源码:路由做映射的配置,以后视图类种方法可以随便命名 ViewSet:ViewSetMixin + APIView ===》适用于:不需要序列化==》路由写法变了 GenericViewSet: ViewSetMixin + GenericAPIView ===》适用于:需要序列化,需要使用数据库==》路由写法变化 ReadOnlyModelViewSet:包含 list和retrieve
drf之路由
# 之前路由写法: path('books/', BookView.as_view()) # 以后一旦继承了ViewSetMixin,就变成了: path('publish/', PublishView.as_view({'get': 'list', 'post': 'create'})) # 这样写起来做映射,可能有些麻烦,于是drf帮我们封装了两个路由类===》可以帮助我们快速生成之前我们写的映射关系 # #############必须是继承ViewSetMixin + APIView及其子类才能自动生成 SimpleRouter和DefaultRouter # 自动生成路由:自动映射如下方法: {'get': 'list', 'post': 'create'} {'get': 'retrieve', 'put': 'update', 'delete': 'destroy'} ## 其他的-->视图类中有别的方法,我们想做映射,需要使用装饰器
使用方式
# 大前提:必须是继承ViewSetMixin + APIView及其子类才能自动生成 ######使用步骤 # url.py 路由文件中 #### 1 导入路由类 from rest_framework.routers import SimpleRouter, DefaultRouter #### 2 类实例化得到对象 router = SimpleRouter() #### 3 自动生成路由,调用对象的某个方法,完成跟视图类的对应关系,映射路由 router.register('publish', Publish, 'publish') router.register('books', BookView, 'books') # 后期可以注册更多 router.register('user',UserView,'user') #### 4 把自动生成的路由,加到总路由中 urlpatterns = urlpatterns + router.url # 两个列表直接相加 # 或者第四步这样写 path('api/v1/', include(router.urls)), # http://127.0.0.1:8000/api/v1/user/register/--->post
SimpleRouter, DefaultRouter
SimpleRouter和DefaultRouter区别
DefaultRouter 生成的路径多一个根路径 api-root
DefaultRouter 会多附带一个默认的API根视图,返回一个包含所有列表视图的超链接相应数据
以后就用:SimpleRouter 就可以
action装饰器
作用:
为视图类中的方法做路径的映射(不包含create、list、destory、retrieve 和 update)
使用方式:
# 在需要映射的方法上增加有参装饰器action @action(methods=['POST'],detail=False) def register(self, request): return Response('register')
自动生成:
http://127.0.0.1:8008/user/register/---->post--->就会执行register
action参数
methods请求方式,可以写多个 detail:路径中是否带id号 http://127.0.0.1:8008/user/register/ # detail=False http://127.0.0.1:8008/user/4/register/ # detail=True
以后继承ModelViewSet也可能会重写好多方法
#### 重写list class PublishView(ModelViewSet): queryset = Publish.objects.all() serializer_class = PublishSerializer def list(self, request, *args, **kwargs): # 以后可能会重写list,做自己的定制 res=super().list(request, *args, **kwargs) return Response({'code':100,'msg':'成功','result':res.data}) ### 重写get_serializer_class def get_serializer_class(self): # 是GenericAPIView类中的方法,返回什么,以后就以哪个序列化类继续操作 print(self.action) if self.request.method=='POST': return WritePublishSerializer else: return self.serializer_class ### 重写perform_create def perform_create(self, serializer): serializer.save() ### 序列化使用PublishSerializer,反序列化使用 WritePublishSerializer
视图类的对象中的action参数
print(self.action) # 视图类的对象中有个action属性---》它是当次请求执行的方法名的字符串 # 通过action可以限制视图类中某个方法使用的序列化类是哪个
标签:get,子类,self,list,视图,class,路由,drf From: https://www.cnblogs.com/zfq132/p/17680524.html