首页 > 其他分享 >drf视图组件,视图集,路由系统,认证组件

drf视图组件,视图集,路由系统,认证组件

时间:2023-02-06 23:46:00浏览次数:37  
标签:get view 视图 --- 组件 序列化 路由 drf

上周回顾

# 1 前端开发模式
-分离和混合
-http 通信  后端都是web后端
-前端:pc桌面开发,web开发,app,小程序--->http--->调用后端--->后端都是一套
        
# 2 api接口
-前后端交互的媒介
url地址:
    https://api.map.baidu.com
请求方式:
    get,post,put,patch,delete
606-331-199请求参数:
    json格式的key-value类型数据
响应结果:
    json格式数据
       
# 3 接口测试工具 postman

# 4 restful规范
1.数据的安全保障 通常使用https协议
2.接口中带api标识
3.多版本共存 路径中带版本信息
4.数据即是资源 均使用名词 尽量不出现动词
5.资源操作由请求方式决定(method)
6.在请求地址带过滤条件
7.响应状态码:两套
    http响应状态码:1xx 请求正在处理 2xx 成功响应 3xx 重定向 4xx 客户端错误 5xx 服务端错误
8.返回数据中带错误信息
9.返回结果应该符合以下规范
     GET 获取所有数据:返回资源对象的列表(数组)[{name:红楼梦,price:99},{name:红楼梦,price:99},{name:红楼梦,price:99}]
        GET 单个对象:返回单个资源对象:{name:红楼梦,price:99}
        POST 新增对象:返回新生成的资源对象:{name:西游记,price:99}
        PUT 修改对象:返回完整的资源对象 :{name:西游记,price:100}
        DELETE 删除:返回一个空文档
10.响应数据中带连接

# 5 drf介绍,快速使用
    
# 6 cbv 执行流程

# 7 APIView执行流程

# 8 Request对象源码

# 9 序列化反序列化
序列化:把我们识别的数据转换成指定格式提供给别人
反序列化:把别人提供的数据转换/还原成我们需要的格式
    
# 10 序列化组件--->写继承类 实例化得到对象
-常用字段和字段参数
-做序列化
  -序列化类实例化--->对象--->传入要序列化的数据 many--->ser.data
  -source
  -SerializerMethodField
  -在表模型中写方法
  -ListField
  -DictField
-做反序列化
  -新增
    -序列化类实例化--->对象--->传入前端的数据--->数据校验--->ser.save
    
  -保存
    -序列化类实例化--->对象--->传入前端的数据和要修改的数据--->数据校验--->ser.save
    -数据校验:字段自己,局部,全局钩子
    
  -重点:
    有时候,序列化字段和反序列化字段,不一样
    -定制的序列化字段,不能用来反
    -read_only和write_only 的使用
    
  -数据校验
    -字段自己
    -局部
    -全局
    
  -ModelSerializer,跟表有关系
   -不用重写create和update
   -字段可以映射过来
   -重写字段
   -给字段类传参数--->extra_kwargs
   -定制字段,跟之前一摸一样
   -fields 列表,必须要有所有字段(序列化,反序列化都要注册--->一定是表模型的字段吗?)

# 11 请求与响应
  -Request 源码
  -能够解析的编码格式
     -全局配置
     -局部配置
        
  -Response 源码
  -能够响应的编码格式
    -全局
    -局部
    
  -drf向响应头中写数据
  -原生django向响应头中写数据
  obj=HttpResponse() --->obj['xx']=yy

# 12 视图 View
  -两个视图基类:APIView  GenericAPIView
  -APIView
    	-执行流程:新的reqeust,三大认证,全局异常
        -重写了as_view,dispatch
        -类属性:parser_class,xxx
        
  -GenericAPIView---》继承了APIView----》以后,如果是跟数据库打交道,尽量用它
    	1 queryset:要序列化或反序列化的表模型数据
        2 serializer_class:使用的序列化类
        3 lookup_field :查询单条的路由分组分出来的字段名
        4 filter_backends:过滤类的配置(了解)
        5 pagination_class:分页类的配置(了解)

        # 方法
        1 get_queryset   :获取要序列化的对象
        2 get_object  :获取单个对象
        3 get_serializer :获取序列化类  ,跟它差不多的get_serializer_class,一般重写它,不调用它
        4 filter_queryset  :过滤有关系(了解)
        
  -补充,根据请求方式,定制序列化类
     def get_serializer(self, *args, **kwargs):
        if self.request.method=='GET':
            return 序列化单条的序列化类
        else:
            return 新增的序列化类
        
#13 5 个视图扩展类----》不是视图类----》必须配合GenericAPIView
	-每个类自己写了一个方法,写的不是【请求方式,不是put,get。。。】的方法,写的是list,destroy。。。
    -minxin 混入,通过多继承来实现多个功能
    -from rest_framework.mixins import CreateModelMixin, UpdateModelMixin, DestroyModelMixin, RetrieveModelMixin,
    ListModelMixin   
    -继承GenericAPIView+某个视图扩展类+请求方式的方法
  • drf之视图组件

  • 视图集

  • 路由系统

  • 认证组件

1 drf之视图组件

# 两个视图基类
# 5个视图扩展类
# 9个视图子类---->视图类,不需要额外继承GenericAPIView,只需要继承9个中其中某个,就会有某个或某几个接口

微信图片_20230206174612

1.1两个视图基类

APIView

导入:from rest_framework.views import APIView
    
APIView是REST framework提供的所有视图的基类,继承了View父类,对原生request对象进行了封装,并重写了dispatch方法,对认证,权限,频率控制,并处理全局异常

没有操作数据库 需要你自己去写get,post

GenericAPIView

导入:from rest_framework.generics import GenericAPIView
    
GenericAPIView继承了APIView增加了序列化数据和序列化的类为Mixin扩展类提供支持

常用属性

属性 作用
queryset 需要序列化的查询集
serializer_class 指定使用的序列化器
pagination_class 分页控制类
filter_backends 过滤控制后端
lookup_field 查询时的查询条件,默认为pk

常用方法

方法 作用
get_queryset() 查询获取所有记录
get_object() 获取一条数据对象
get_serializer() 获取配置的序列化类

1.2五个视图扩展类

扩展类 提供方法 用途
ListModelMixin list() 获取多条数据对象
CreateModelMixin create() 新增单一数据对象
RetrieveModelMixin retrieve() 获取单一数据对象
UpdateModelMixin update() 更新一条数据对象
DestroyModelMixin destroy() 删除一条数据对象

1.3九个子类视图

子类 提供方法 继承自
CreateAPIView 提供 post 方法 GenericAPIView CreateModelMixin
ListAPIView 提供 get 方法 GenericAPIView ListModelMixin
RetireveAPIView 提供 get方法 GenericAPIView RetrieveModelMixin
DestoryAPIView 提供 delete 方法 GenericAPIView DestoryModelMixin
UpdateAPIView 提供 putpatch 方法 GenericAPIView UpdateModelMixin
ListCreateAPIView 提供 getpost方法 GenericAPIView ListModelMixin CreateModelMixin
RetrieveUpdateAPIView 提供 getputpatch方法 GenericAPIView RetrieveModelMixin UpdateModelMixin
RetrieveDestroyAPIView 提供 getputpatch方法 GenericAPIView RetrieveModelMixin DestoryModelMixin
RetrieveUpdateDestoryAPIView 提供getputpatchdelete方法 GenericAPIView RetrieveModelMixin UpdateModelMixin DestoryModelMixin
# 路由
urlpatterns = [
    path('books/', views.BookView.as_view()),
    path('books/<int:pk>/', views.BookView.as_view()),
]

# 视图类
from .models import Book
from .serializer import BookSerializer
from rest_framework.generics import ListAPIView, ListCreateAPIView, CreateAPIView, RetrieveAPIView, \
    RetrieveUpdateDestroyAPIView, RetrieveDestroyAPIView
    
class BookView(ListCreateAPIView):  # 查询所有,新增一个
    queryset = Book.objects.all()
    serializer_class = BookSerializer

# 新增一个,修改一个,删除一个
class BookDetailView(RetrieveUpdateDestroyAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

image-20230206202709568

2 视图集

2.1 ViewSet

继承 : APIView、 ViewSetMixin

ViewSet视图集类不再实现get()、post()等方法,而是实现动作action如list() 、create() 等

视图集只在使用as_view()方法的时候,才会将action动作与具体请求方式对应上

2.2 ReadOnlyModelViewSet

继承:RetrieveModelMixin、ListModelMixin、GenericViewSet

2.3 ModelViewSet

继承了五个视图扩展类

2.4 通过ReadOnlyModelViewSet编写5个接口

'''
如果两个视图类写成一个 路由会有两个get 路由路径也不一样
drf写了一个类,ModelViewSet,只要继承它,5个接口都有了,但是路由变了
    -重点:一旦继承ModelViewSet,路由写法变了---->变成 .as_view({'get': 'list'})
    路由做映射,意思是如果get请求,访问这个地址,就执行视图类的list方法
'''
# 路由
urlpatterns = [
    path('books/', views.BookView.as_view({'get': 'list', 'post': 'create'})),
    path('books/<int:pk>/', views.BookView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
]

# 视图类
class BookView(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

image-20230206204840900

image-20230206204920968

2.5 通过ReadOnlyModelViewSet编写2个只读接口

# 路由
urlpatterns = [
    path('books/', views.BookView.as_view({'get': 'list'})),
    path('books/<int:pk>/', views.BookView.as_view({'get': 'retrieve'})),
]

# 视图类
class BookView(ReadOnlyModelViewSet):  # 只有查询所有和查询单个
    queryset = Book.objects.all()
    serializer_class = BookSerializer

image-20230206205730596

image-20230206205757737

2.6 ViewSetMixin源码分析

# 请求来了,路由匹配成功---》get请求,匹配成功books,会执行  views.BookView.as_view({'get': 'list', 'post': 'create'})()------>读as_view【这个as_view是ViewSetMixin的as_view】

    @classonlymethod
    def as_view(cls, actions=None, **initkwargs):
        # 如果没有传actions,直接抛异常,路由写法变了后,as_view中不传字典,直接报错
        if not actions:
            raise TypeError("The `actions` argument must be provided when "
                            "calling `.as_view()` on a ViewSet. For example "
                            "`.as_view({'get': 'list'})`")
		# 。。。。其他代码不用看
        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            if 'get' in actions and 'head' not in actions:
                actions['head'] = actions['get']
            self.action_map = actions
            for method, action in actions.items():
                handler = getattr(self, action)
                setattr(self, method, handler)

            return self.dispatch(request, *args, **kwargs)
        # 去除了csrf校验
        return csrf_exempt(view)
    
    
# 路由匹配成功执行views.BookView.as_view({'get': 'list', 'post': 'create'})()----》本质执
行ViewSetMixin----》as_view----》内的view()---》代码贴过来
    def view(request, *args, **kwargs):
            #actions 是传入的字典--->{'get': 'list', 'post': 'create'}
            self.action_map = actions
            # 第一次循环:method:get,action:list
            # 第一次循环:method:post,action:create
            for method, action in actions.items():
                # 反射:去视图类中反射,action对应的方法,action第一次是list,去视图类中反射list方法
                # handler就是视图类中的list方法
                handler = getattr(self, action)
                # 反射修改:把method:get请求方法,handler:list
                # 视图类的对象的get方法,变成了list
                setattr(self, method, handler)

            return self.dispatch(request, *args, **kwargs) #dispatch是APIView的
        
        
        
 # 总结:
	-1 只要继承ViewSetMixin的视图类,路由写法就变了(重写了as_veiw)
    -2 变成需要需要传入字典映射方法:{'get': 'list', 'post': 'create'}
    	-只要传入actions,以后访问get就是访问list,访问post,就是访问create
    -3 其他执行跟之前一样 
    -4 以后视图类类中的方法名,可以任意命名,只要在路由中做好映射即可【重要】

2.7 from rest_framework.viewsets包下的类

'''
from rest_framework.viewsets下有这几个类
ModelViewSet:5个试图扩展类+ViewSetMixin+GenericAPIView
ReadOnlyModelViewSet::2个视图扩展类+ViewSetMixin+GenericAPIView   只读的两个
ViewSetMixin:魔法,重新了as_view,只要继承他,以后路由写法变成了映射方法
ViewSet:ViewSetMixin+ APIView
GenericViewSet:ViewSetMixin + GenericAPIView
'''


#重点:
	以后,你想继承APIView,但是想变路由写法【视图类中方法名任意命名】,要继承ViewSet
    以后,你想继承GenericAPIView,但是想变路由写法【视图类中方法名任意命名】,要继承GenericViewSet

3 视图层大总结

# 1 两个试图基类
	-APIView,GenericAPIView
# 2 5个试图扩展类,不是视图类,必须配合GenericAPIView

# 3 9 个视图子类,是视图类,只需要继承其中某一个即可

# 4 视图集 
	-ModelViewSet:路由写法变了,只需要写两行,5个接口都有了
    -ReadOnlyModelViewSet:路由写法变了,只需要写两行,2个只读接口都有了
    -ViewSetMixin:不是视图类,魔法,重写了as_view,路由写法变了,变成映射了
    	views.BookView.as_view({'get': 'list', 'post': 'create'})
    -ViewSet:ViewSetMixin + APIView
	-GenericViewSet:ViewSetMixin+ GenericAPIView

    
    
# 举例子:发送短信接口,视图类叫SendView,方法叫send_sms,路由配置变了
	get--->send_sms
	class SendView(ViewSet):
        def send_sms(self,request):
            

4 路由系统

4.1 自动生成路由

# drf 由于继承ViewSetMinxin类,路由写法变了
   -原生+drf,以后的路由写法,可能会有如下情况(三种情况)
      -path('books/',views.BookView.as_view())
      -path('books/',views.BookView.as_view({'get':'list','post':'create'}))
      -自动生成
        
# drf提供了两个路由类,继承ModelViewSet后,路由可以自动生成

# 使用步骤
# 第一步:导入路由类
from rest_framework.routers import SimpleRouter

# 第二步:实例化得到对象(两个类,一般使用SimpleRouter)
router = SimpleRouter()

# 第三步:注册
router.register('books', views.BookView, 'books')

# 第四步:在urlpatterns中注册,两种方式
# 方式一:
urlpatterns += router.urls
# 方式二:
导入 from django.urls import path,include
include:path('/api/v1/', include(router.urls))  方式多一些

image-20230206221436207

from rest_framework.routers import DefaultRouter
# 第二步:
router = DefaultRouter() # 生成多,多了几个:1 Api Root:访问根,可以看到有哪些地址,比如book的,比如publish的

image-20230206222250078

# 底层实现:自动生成路由就是
       -本质是自动做映射,能够自动成的前提是,视图类中要有 5个方法的某要给或多个
           get--->list
           get--->retrieve
           put--->update
           post--->create
           delete--->destory
       -ModelViewSet,ReadOnlyModelViewSet可以自动生成
              
       -9个试图子类+配合ViewSetMixin   才可以自动生成
       -GenericAPIView+5个试图扩展类+配合ViewSetMixin   才能自动生成

4.2 action 装饰器

# action 写在视图类的方法上,可以自动生成路由

# 使用步骤
写在视图类方法上
class SendView(ViewSet):
    @action(methods=['GET'], detail=False, url_path='send_sms', url_name='send_sms')
    # methods指定请求方法,可以传多个
    # detail:只能传True和False
         -False,不带id的路径:send/send_sms/
         -True,带id的路径:send/2/send_sms/
    #url_path:生成send后路径的名字,默认以方法名命名 
    # url_name:别名,反向解析使用,了解即可
    
    def send_sms(self, request):
        phone = request.query_params.get('phone')
        print(f'发送成功{phone}')
        return Response({'code': 100, 'msg': '发送成功'})

image-20230206231632768

image-20230206231809760

 # 以后看到的drf路由写法
	后期,都是自动生成,一般不在urlpatterns 加入路由了
# 补充:
	-1 不同请求方式可以使用不同序列化类
    -2 不同action使用不同序列化类
class SendView(GenericViewSet):
    queryset = None
    serializer_class = '序列化类'

    def get_serializer(self, *args, **kwargs):
        if self.action=='lqz':
            return '某个序列化类'
        else:
            return '另一个序列化列'
    @action(methods=['GET'], detail=True)
    def send_sms(self, request,pk):
        print(pk)
        # 手机号,从哪去,假设get请求,携带了参数
        phone = request.query_params.get('phone')
        print('发送成功,%s' % phone)
        return Response({'code': 100, 'msg': '发送成功'})

    @action(methods=['GET'], detail=True)
    def lqz(self,request):  # get
        # 序列化类
        pass

    @action(methods=['GET'], detail=True)
    def login(self,request):  # get
        # 序列化类
        pass

5 认证组件

# 访问某个接口,需要登陆后才能访问

# 第一步:写个登录功能,用户表
	-User表
    -UserToken表:存储用户登录状态 [这个表可以没有,如果没有,把字段直接写在User表上也可以]

5.1 登录接口

#### 表模型

class User(models.Model):
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=32)



class UserToken(models.Model):  # 跟User是一对一
    token = models.CharField(max_length=32)
    user = models.OneToOneField(to='User', on_delete=models.CASCADE, null=True)
    # user :反向,表名小写,所有有user字段

### 路由
router.register('user', views.UserView, 'user')  # /api/v1/user/login     post 请求

# 视图类
####  登录接口  自动生成路由+由于登录功能,不用序列化,继承ViewSet
from .models import User, UserToken
import uuid


class UserView(ViewSet):
    @action(methods=['POST'], detail=False)
    def login(self, request):
        username = request.data.get('username')
        password = request.data.get('password')
        user = User.objects.filter(username=username, password=password).first()
        if user:
            # 用户存在,登录成功
            # 生成一个随机字符串--uuid
            token = str(uuid.uuid4())  # 生成一个永不重复的随机字符串
            # 在userToken表中存储一下:1 从来没有登录过,插入一条,     2 登录过,修改记录
            # 如果有就修改,如果没有就新增  (if 自己写)
            # kwargs 传入的东西查找,能找到,使用defaults的更新,否则新增一条
            UserToken.objects.update_or_create(user=user, defaults={'token': token})
            return Response({'code': '100', 'msg': '登录成功', 'token': token})
        else:
            return Response({'code': '101', 'msg': '用户名或密码错误'})

5.2 认证功能

标签:get,view,视图,---,组件,序列化,路由,drf
From: https://www.cnblogs.com/super-xz/p/17097041.html

相关文章

  • drf9个视图子类,2个视图集,路由系统,认证组件
    上周内容大回顾前后端开发模式前后端混合模式 1.前端写好交给后端用后端模板语法,把数据补上去2.前后端全栈,都有一个人写前后端分离 1.前端写前端,后端就只写接口......
  • 9视图子类 2个视图子类 路由系统自动生成路由 action装饰器 认证组件登入接口
    目录回顾9个视图子类2个视图集通过ModelViewSet编写5个接口通过ReadOnlyModelViewSet编写2个只读接口ViewSetMixin源码分析fromrest_framework.viewsets包下的类视图层大......
  • drf之路由系统
    目录路由系统自动生成路由action装饰器补充知识路由系统drf由于继承ViewSetMixin类,路由写法就改变了路由的三种写法1.path('books/',views.BookView.as_view())2.path......
  • drf之认证组件
    目录认证组件登录接口认证功能认证组件访问某个接口,需要登录后才能访问编写模型表classUser(models.Model):username=models.CharField(max_length=32)pa......
  • 9 个视图子类、视图集、路由系统、认证组件
    9个视图子类、视图集、路由系统、认证组件9个视图子类#两个视图基类APIViewGenericAPIView1.APIView执行流程:新的request,三大认证,全局异常重写了as_vi......
  • drf-视图集、路由系统、action装饰器
    1.9个视图扩展类1.两个视图基类:APIView、GenricAPIView2.5个视图扩展类:CreateModelMixin,UpdateModelMixin,RetrieveModelMixin,ListModelMixin,DestroyModelMixin3.9......
  • DRF06
    9个视图子类 之前学的是:有两个视图基类,5个扩展类今天学的是:9个是视图子类:他就是真的视图类,就不需要继承GenerricAPIView,只要继承者9个中的其中一个,就会有某个,或者......
  • drf6
    今日内容概要9个视图子类视图集路由系统认证组件今日内容详细9个视图子类fromrest_framework.genericsimportCreateAPIView,ListAPIView,UpdateAPIView,Ret......
  • DRF - 视图组件
    视图组件drf的视图,视图类学过APIViewdrf的基类,drf提供的最顶层的类0、APIView与Django原生的View类的区别1.APIView中传入视图方法中的Request对象是RESTframework......
  • drf 自动生成路由
    目录drf路由系统SimpleRouter与DefaultRouteraction装饰器扩展测试伪代码drf路由系统由于继承了ViewSetMinxin类路由的写法变了,有三种写法。需要学习一下原生写法pa......