首页 > 其他分享 >9个视图子类、视图集、drf之路由

9个视图子类、视图集、drf之路由

时间:2023-09-05 18:45:03浏览次数:33  
标签:get 子类 self list 视图 class 路由 drf

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

相关文章

  • 9个视图子类
    视图类五层第一层:继承APIview,五个接口第二层:GenericAPIView,继承APIview(两个类属性+defgetpostgetputdelete)第三层:五个视图扩展类GenericAPIView+(RetrieveModelMixin,CreateModelMixin,DestroyModelMixin,ListModelMixin,UpdateModelMixin)(两个类属性+defgetpostget......
  • drf-day7
    九个视图子类以后想写5个接口中的某一个或某几个或所有,只需要选择继承不同的类即可,类中只需要配置两个类属性queryset=Publish.objects.all()serializer_class=PublishSerialize使用九个视图子类两个综合类来写五个接口fromrest_framework.genericsimportListCrea......
  • drf之请求,drf 之响应,drf之响应格式,两个视图基类,基于GenericAPIView,5个视图扩展类
    drf之请求1.1之请求Request类#data#query_params#用起来跟之前一样了解: request._request视图类的方法中:self是咱们写的视图类的对象,self.request是新的request,self.request是一个HttpRequest对象,它提供了许多属性和方法来访问和处理请求的信息.1.2......
  • drf-视图组件
    一、视图DjangoRESTframwork提供的视图的主要作用:控制序列化器的执行(检验、保存、转换数据)控制数据库查询的执行RESTframework提供了众多的通用视图基类与扩展类,以简化视图的编写。1. 两个视图基类1.1APIViewfromrest_framework.viewsimportAPIViewAPIView......
  • drf请求和响应、GenericAPIView封装、5个视图扩展类
    一、drf之请求1、drf之请求Request类视图类继承APIView后多了-0去除了csrf认证-1新的request-request.data-request.query_params-request.其他跟之前一样-request._request是老的-2三大认证-3全局异常2、控制前端请求的编码格式fromrest_fra......
  • drf请求
    drf请求之Request类1、新的request视图层的方法中的request都是这个类(fromrest_framework.requestimportRequest)的对象2、使用request.data取请求体中的数据(之前的Json传值request.body)3、使用request.query_params取请求参数中的数据4、其他属性,用起来和之前一样......
  • Prism视图模型定位器(ViewModelLocator)
    视图模型定位器(ViewModelLocator)依照“标准命名约定”将视图(View)中的数据上下文链接到视图模型(ViewModel)的实例。自动绑定视图模型Prism视图模型定位器(ViewModelLocator)有一个AutoWireViewModel属性:当设置为true时,AutoWireViewModelChanged事件调用类中的ViewMod......
  • 视图开发 命令式 声明式 将视图和数据分离
    10|Widget中的State到底是什么?https://time.geekbang.org/column/article/108576 下述代码分别展示了在Android、iOS及原生Javascript中,如何将一个文本控件的展示文案更改为HelloWorld://Android设置某文本控件展示文案为HelloWorldTextViewtextView=(TextView)f......
  • django+drf开发一些个人的标准化
    最近在改造一下个人的开发风格。特分享一下。子应用我一般放在apps中,每个不同模块的子应用起不同的名字。startapp后自己移动一下,记得修改一下Appconfig中的name即可。子应用中创建services.py或者如有需要可以创建services模块再细分。所有业务放到services中编写。views一律......
  • ORA-01031: insufficient privileges 19c跨用户视图查询 with grant option
    问题概述某客户从11.2.0.1升级迁移到19.16版本后,应用反应部分查询功能无法使用报无权限,数据库中增加了ORA-01031:insufficientprivileges跟踪event进行分析问题复现创建三个测试用户createusertest1identifiedbyoracle123;createusertest2identifiedbyoracle123;......