6-drf-9个视图子类、视图集(ModelViewSe、ViewSetMixin)、drf路由(使用方式、action装饰器)、视图类的对象中的action参数

1 9个视图子类

2 视图集
2.1 ModelViewSet
2.2 ViewSetMixin
2.3 ReadOnlyModelViewSet
2.4 视图层中类的总结

3 drf之路由
3.0 drf路由使用方式
3.1 SimpleRouter, DefaultRouter
3.2 action装饰器
3.3 以后继承ModelViewSet也可也能会重写好多方法
3.3 视图类的对象中的action参数

1 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.1 视图类

#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)

1.2 路由

path('publish/', PublishView.as_view()),
path('publish/<int:pk>', PublishView.as_view()),

2 视图集

2.1 ModelViewSet

# 1 只要视图类继承了它,路由写法改一下,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'})),

2.1.1 ModelViewSet源码分析

# 有查询所有接口
	-get--list----》拿到所有数据,序列化--返回
    
# 新增一条
	-post---create---》之前咱们写的新增的代码一样的
    
    
    
# 为什么get 就变成了list
# 为什么post 就变成了create

2.2 ViewSetMixin

# 没见过
# ViewSetMixin 决定了,以后路由写法就变了
	-path('publish/', PublishView.as_view({'get':'list','post':'create'}))
    -path('publish/', PublishView.as_view({'get':'lin'}))
    
# 源码分析
	-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方法

2.2.1 以后视图类中方法名可以随意命名,只要路由做好映射

# 继承的类是:只要继承ViewSetMixin ,就能视图类中方法任意命名,路由写法变化
class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
    pass

class ModelViewSet(mixins.CreateModelMixin, mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin, mixins.DestroyModelMixin,
                   mixins.ListModelMixin, GenericViewSet)
   

# 视图类                
from rest_framework.viewsets import ModelViewSet


class PublishView(ModelViewSet):
    queryset = Publish.objects.all()
    serializer_class = PublishSerializer

    def login(self, request):
        return Response('login')

# 路由 
path('login/', PublishView.as_view({'post': 'login'})),

######## 例如,用户注册
from rest_framework.viewsets import ViewSetMixin, ViewSet


# class UserView(ViewSetMixin, APIView):
class UserView(ViewSet):  # ViewSetMixin + APIView = ViewSet
    def register(self, request):
        return Response('register')
        
path('register/', UserView.as_view({'post': 'register'})),

2.3 ReadOnlyModelViewSet

# 以后写的接口,只想有 获取单条和获取所有,继承它

2.4 视图层中类的总结

# 1 两个视图基类
	-APIView和GenericAPIView
    -APIView的执行流程:包装了新的  处理了csrfrequeset,执行了3大认证,处理全局异常
    -GenericAPIView:要做序列化,要跟数据库打交道,就直接继承它即可
    	-queryset
        -serializer_class
        
        -get_object
        -get_queryset
        -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
    
    
# 4 视图集
	-ModelViewSet:
    	-ViewSetMixin+GenericAPIView+5个视图扩展类
        -GenericViewSet+5个视图扩展类
        
    -ViewSetMixin源码:路由做映射的配置,以后视图类中方法可以随便命名
    -Viewset:ViewSetMixin+APIView---》不需要要序列化,路由写法变了
    -GenericViewSet:ViewSetMixin+GenericAPIView--》需要序列化,需要用数据库,路由写法变化
    -ReadOnlyModelViewSet:list和retrieve

3 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'}



## 其他的-->视图类中有别的方法,我们想做映射,需要使用装饰器

3.0 drf路由使用方式

# 大前提:必须是继承ViewSetMixin+APIView及其子类才能自动生成
####使用步骤
# urls.py中

#### 1 导入路由类
from rest_framework.routers import SimpleRouter, DefaultRouter

#### 2 类实例化得到对象
router = SimpleRouter()

#### 3 自动生成路由,调用对象的某个方法,完成跟视图类的对应关系,映射路由
router.register('publish', PublishView, 'publish')
# router.register('books', BookView, 'books') #  后期可以注册更多
router.register('user',UserView,'user')

##### 4 把自动生成的路由,加到总路由中
urlpatterns = urlpatterns + router.urls  # 两个列表直接相加

### 第四步可以这样写
	path('api/v1/', include(router.urls)),   # http://127.0.0.1:8008/api/v1/user/register/--->post

3.1 SimpleRouter, DefaultRouter

SimpleRouter, DefaultRouter区别
	-DefaultRouter生成的路径多一个根路径 api-root
    -DefaultRouter会多附带一个默认的API根视图,返回一个包含所有列表视图的超链接响应数据
以后就用:SimpleRouter就可以

3.2 action装饰器

# 作用:为视图类中的方法做路径的映射
	-这些方法排除5个 :create,list,destroy。。。
    
# 使用方式
    @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

3.3 以后继承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   

3.3 视图类的对象中的action参数

print(self.action)  
# 视图类的对象中有个action属性---》它是当次请求执行的方法名的字符串

# 通过action可以限制视图类中某个方法使用的序列化类是哪个
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值