首页 > 其他分享 >视图集ModelViewSet drf之路由 认证组件

视图集ModelViewSet drf之路由 认证组件

时间:2023-12-26 22:45:17浏览次数:30  
标签:ModelViewSet self list 视图 --- 图集 view 路由 drf

视图集ModelViewSet

ModelViewSet

-视图类:GenericAPIView(继承)
- 路由映射:list  create  retrieve update destroy
继承5个视图扩展类:
CreateModelMixin,ListModelMixin,UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin
-路由写法改变:ViewSetMixin 只要继承它,路由写法就的改变

-分析:ViewSetMixin  不是视图类,支持路由映射的写法,核心原理是重写了as_view
-请求来了
	原来:执行APIView--》as_visw内的view(request)
    执行 ViewSetMixin的---》as_view内的 view(request)
源码分析:as_view
def as_view(cls, actions=None, **initkwargs):
# actions={'get': 'list', 'post': 'create'}
      def view(request, *args, **kwargs):
            self = cls(**initkwargs)#self是BookView视图类的对象
            self.action_map = actions#actions这个字典
            for method, action in actions.items():
                #method:get   action:list
                #去实体类的对象中 self中 反射list的方法
                #handler就是BookView(父类)中的list方法
                handler = getattr(self, action)#反射action(list),反射设置值--》把method:get,设置成了list
                #BookView类的对象,以后get方法就是list方法
                setattr(self, method, handler)
             # 根据请求方式执行跟请求方式同名的方法  get请求---》get方法---》list
            self.request = request
            self.args = args
            self.kwargs = kwargs

          
            return self.dispatch(request, *args, **kwargs)
 -ViewSetMixin的总结--》只要继承它
		-以后路由写法as_view必须传字典---》映射关系
    	-什么请求方式---》执行视图类中什么方法 的映射关系
#ViewSetMixin必须写在视图类前
#2  ViewSetMixin类--》路由写法变了的

#3  ViewSet:以后想继承APIView,但是路由写变了,就继承它
	
#4  GenericViewSet:以后想继承GenericViewSet,但是路由写变了,就继承它
#5 ReadOnlyModelViewSet:只读
    -视图类:GenericAPIView
    - 映射:list    retrieve :只查询,查询所有和查询单条ListModelMixin,RetrieveModelMixin
    -路由写法变了:ViewSetMixin
# 视图类,继承ReadOnlyModelViewSet,不能多写,写多了会报错
# path('books/', views.BookView.as_view({'get': 'list'})),
# path('books/<int:id>', views.BookView.as_view({'get': 'retrieve'})),

视图层(小概括):

# 视图层:
# 两个视图基类
	APIView
    GenericAPIView
# 5个视图扩展类---》不是视图类,必须结合GenericAPIView
        CreateModelMixin:create---》原来咱们post中得代码,新增
        ListModelMixin:list---》原来获取所有
        RetrieveModelMixin:retrieve---》原来获取单条
        UpdateModelMixin:update--->修改
        DestroyModelMixin:destroy--》删除
# 9个视图子类
	    CreateAPIView
        ListAPIView
        RetrieveAPIView
        DestroyAPIView
        UpdateAPIView
        ListCreateAPIView
        RetrieveUpdateDestroyAPIView
        RetrieveDestroyAPIView
        RetrieveUpdateAPIView
           
# 视图集:
	ModelViewSet:所有
    ReadOnlyModelViewSet:只读
    ViewSetMixin:路由写法变了
    ViewSet:ViewSetMixin+APIView
    GenericViewSet:ViewSetMixin+GenericAPIView

1703591517555.png

### 现在有很多视图类,不知道选哪个,具体实战
# 1 publish的5个接口--ModelViewset
# 2 publish的5个接口,获取所有,带code和msg--ModelViewset--》重写list
        # def list(self, request, *args, **kwargs):
        #     res = super().list(request, *args, **kwargs)
        #     return Response({'code': 100, 'msg': '查询所有成功', 'result': res.data})
# 3 写 查询所有,修改一条,路由写法变了
# ViewSetMixin,GenericAPIView
#ListModelMixin,UpdateModelMixin
# from rest_framework.mixins import ListModelMixin,UpdateModelMixin
# class BookView(ViewSetMixin,GenericAPIView,ListModelMixin,UpdateModelMixin):
#     queryset = Book.objects.all()
#     serializer_class = BookSerializer
    #路由
    # path('books/', views.BookView.as_view({'get': 'list'})),
    # path('books/<int:id>', views.BookView.as_view({'put': 'update'})),
    
    
# 4 用户视图类,有登录(login)和注册(register)接口--->第一个跟数据库打交道,第二 做序列化
# class UserView(ViewSet):
#     def login(self):
#         pass
#     def register(self):
#         pass
# path('login/', views.UserView.as_view({'post': 'login'})),
# path('register/', views.BookView.as_view({'post': 'register'})),

# 5 新增一条图书,路由写法变了
# from rest_framework.generics import CreateAPIView
# class BooView(ViewSetMixin,CreateAPIView):
#     queryset = None
#     serializer_class = None
#     #path('books/', views.UserView.as_view({'post': 'create'})),


# 6 查询一条和删除
from rest_framework.generics import RetrieveDestroyAPIView

# class BooView(RetrieveDestroyAPIView):
# class BooView(GenericAPIView,RetrieveModelMixin,DestroyModelMixin):
#     queryset = None
#     serializer_class = None

drf之路由

# 0 视图类没有继承了ViewSetMixin,路由写法跟之前一样
	path('books/', views.BookView.as_view())
# 1 只要视图类继承了ViewSetMixin,路由写法必须写成映射的方式
	path('books/', views.BookView.as_view({'get': 'list'})),
    
    

只要视图类继承了ModelViewSet,还可以这么写

    #1 导入

    from rest_framework.routers import SimpleRouter

    #2 实例化

    router = SimpleRouter()

    #3 注册路径

    router.register('books', views.BookView, 'books')

    #4 加入到路由中

    urlpatterns += router.urls
    
      # 5 list,create,retrieve,destroy,update--->自动映射--》SimpleRouter

假设视图类中有个login,如何做对应?

from rest_framework.decorators import action

class BookView(ModelViewSet):

    queryset = Book.objects.all()

    serializer_class = BookSerializer

# list,create,retrieve,destroy,update--->自动映射--》SimpleRouter
# 手动映射
#methods=None, 请求方式
# detail=None,  只能写True或False,如果写了false就是不带pk的路径,如果写了True路径带pk
	# False的情况: http://127.0.0.1:8080/api/v1/books/login/
    # True 的情况: 				  http://127.0.0.1:8080/api/v1/books/8/login/
# url_path='login' 路径,会在之前的路径上,拼这个路径,如果不写默认以函数名拼接
    # - http://127.0.0.1:8080/api/v1/books/login/
# url_name=None :别名,用做反向解析
@action(methods=['POST'],detail=False,)
def login(self,request):
    return Response('login')

总结:以后只要继承ViewSetMixin,就可以使用SimpleRouter方式写路由

	#1 导入
    from rest_framework.routers import SimpleRouter,DefaultRouter
    #2 实例化 :SimpleRouter,DefaultRouter
    router = SimpleRouter()
    或:认为他们一样即可---》DefaultRouter多一条路径
    router = DefaultRouter()
    #3 注册路径
    router.register('books', views.BookView, 'books')
    #4 加入到路由中:
    # 方式一:(用这个)
    urlpatterns += router.urls
    # 方式二:
    urlpatterns = [
        path('', include(router.urls)),
    ]
    # 5 list,create,retrieve,destroy,update--->自动映射--》SimpleRouter
    # 6 视图类中自己的方法,再做映射--action装饰器
    @action(methods=['POST'],detail=False,)
    def login(self,request):
        return Response('login')

认证组件

认证---》登录认证

-登录进系统后,以后再访问接口,需要携带登录信息,如果没携带,不允许方法---》这个控制就是认证
-cookie(客户端浏览器上)和session(后端存储的键值对)

模块层

#### 用户表,用来做登录
### 用户登录成功户,存登录状态
class User(models.Model):
    name = models.CharField(max_length=64)
    password = models.CharField(max_length=64)
    gender = models.CharField(max_length=64, default="男")
    # user_token = models.OneToOneField(to='UserToken')


class UserToken(models.Model):
    user = models.OneToOneField(to='User', on_delete=models.CASCADE)
    token = models.CharField(max_length=64)

视图层


import uuid
from .auth import LoginAuth
class BookView(ReadOnlyModelViewSet):  # list  retrieve
    authentication_classes = [LoginAuth]  # 5个接口必须登录才能呢访问
    # 配置两个类属性
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    def list(self, request, *args, **kwargs):
        res = super().list(request, *args, **kwargs)
        return Response({'code': 100, 'msg': '查询所有成功', 'result': res.data})
from .models import User, UserToken
class UserView(ViewSet):
    @action(methods=['POST'],detail=False)
    def login(self,request):
        # 前端传入的username和password  request.data
        username = request.data.get('username')
        password = request.data.get('password')
        user = User.objects.filter(name=username, password=password).first()
        if user:
            # 生成 随机字符串,放到UserToken表中,把随机字符串返回给前端
            token = str(uuid.uuid4())
            # 如果之前UserToken表中有记录,就要更新,如果没有记录,就要新增
            # 先去UserToken查,如果查到,更新 update更新,查不到UserToken.objects.crete()
            # 有就更新,没有就新增
            # 通过user_id=user.pk去查询,能查到,使用defaults中得值更新,更新token
            # 如果查不到,使用 通过user_id=user.pk,token=token 新增一条
            UserToken.objects.update_or_create(defaults={'token': token}, user_id=user.pk)
            return Response({'code': '100', 'msg': '登录成功', 'token': token})
        else:
            return Response({'code': '101', 'msg': '用户名或密码错误'})



标签:ModelViewSet,self,list,视图,---,图集,view,路由,drf
From: https://www.cnblogs.com/zhangfanshixiaobai/p/17929537.html

相关文章

  • drf之视图集类、5个视图扩展类、9个视图子类、视图集
    两个视图基类#APIView--->之前一直在用---》drf提供的最顶层的父类---》以后所有视图类,都继承自它#GenericAPIView--》继承自APIView--》封装继承APIView+序列化类+Response写接口APIView是RESTframework提供的所有视图的基类,继承自Django的View父类。APIView与View的不......
  • drf 入门--精通 07days
    视图层总结 视图集ModelViewSet-视图类:GenericAPIView-映射:listcreateretrieveupdatedestroyCreateModelMixin,ListModelMixin,UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin-路由写法变了:ViewSetMixin只要继承它,路由写法变了......
  • drf之断言、请求、响应
    反序列化校验源码分析反序列化校验,什么时候,开始执行校验(切入点) -视图类中的ser.is_valid(),就会执行校验,校验通过返回True,不通过返回False入口:ser.is_valid()是序列化类的对象,假设序列化类是BookSerializer---》我们在他的内部找is_valid---》找不到,找到父类的父类BaseSer......
  • Python DRF基础使用01
    目录1,web应用模式(了解)2,restful风格介绍(了解)3,restful设计风格(了解)4,restful案例(了解)5,数据准备6,查询所有数据(理解)7,创建对象(理解)8,获取单个对象(理解)9,修改单个对象(理解)10,删除单个对象(理解)11,DRF魅力展示(了解)12,序列化器概述(了解)13,序列化器定义(掌握)1......
  • Python DRF基础使用02
    目录1,ModelSerializer2,fields3,read_only_fields4,extra_kwargs5,APIView之request6,APIView之Response7,APIView实现列表视图8,APIView实现详情视图(带着id请求,所以叫做详情)9,二级视图,实现列表视图10,二级视图,实现详情视图11,get_object方法(三属性三方法其中一个)12,MiXin(提......
  • drf高级之——定制返回字段
    方案一:在表模型(models)中写,在序列化类中映射模型层书写:defpublish_detail(self):return{'name':self.publish.name,'city':self.publish.city} 序列化类(serializer)中书写:publish_detail=serializers.DictField(read_only=True) 前端打印:"publish_det......
  • drf之序列化类
    序列化类介绍1序列化qs对象,单个对象做序列化给前端2反序列化数据校验:前端传入数据---》校验数据是否合法3反序列化---》前端传入数据,存到数据库中#因为咱么在写接口时,需要序列化,需要反序列化,而且反序列化的过程中要做数据校验---》drf直接提供了固定的写法,只要按照固......
  • drf
    Web开发模式前后端混合开发模式:前端写模板,后端处理完数据再渲染后再传给前端展示效果前后端分离开发模式:前端发送请求把数据传给后端,后端查询数据处理完以json格式返回给前端,前端渲染完展示页面API接口API四大特点#api接口:通过网络,规定了前后台信息交互规则的url链......
  • drf之APIView分析与Request分析
    一、APIView执行流程分析1.1基于APIView+JsonResponse编写接口#原来基于django原生的View编写接口#drf提供给咱们的一个类,以后使用drf写视图类,都是继承这个类及其子类,APIView本身就是继承了Django原生的ViewclassBookView(APIView):defget(self,request):......
  • drf入门到精通 day3
    APIView执行流程分析1在路由中:path('books/',views.BookView.as_view()),请求来了#2先看as_view()---->APIView的as_view---》as_view执行结果跟之前一样,去除了csrf认证@classmethoddefas_view(cls,**initkwargs):view=super().as_view(**initkwa......