drf-day13

发布时间 2023-09-13 19:01:05作者: Py玩家

drf 大回顾

1 drf 入门规范
2 序列化组件---(最重要)
3 请求与响应
4 视图组件----(重要)
5 路由组件
6 认证,权限,频率---重要
7 过滤,排序,分页,全局异常
8 接口文档
9 jwt认证
10 权限:acl,rbac

drf入门规范

前后端开发模式

混合(前后端不分离)---》图书管理系统,bbs项目
分离:后端只负责写接口

API接口

后期写的那些接口,前后端交互的媒介
        请求地址
        请求方式
        请求参数:地址,请求体
        返回数据
写了接口给谁用? 前端(web,app),提供给第三方调用

接口测试工具

发送http请求工具
get请求可以在请求体中携带数据
get请求和post请求有什么区别?
请求编码格式:
        urlencoded:key=value&key=value,后端django封装request.POST
        form-data: 数据和文件混到一起,后端django,request.FILES,request.POST
        json: {name:lqz,age:19},后端django,request.body,装饰器
    collections创建,保存导出

restful规范

1.保证数据安全,通常采用https协议
2.接口携带api标识
3.可以对哦版本共存
4.数据就是资源,前后端交互称之为资源
5.资源的操作由请求方式决定
6.过滤、排序等可以再url上一传参的形式进行搜索
7.相应状态码
8.错误处理,返回错误信息
9.返回结果,针对不同操作,服务器向用户返回的结果应该符合以下规范
10. 需要url请求的资源需要访问资源的请求链接

 序列化和反序列化

序列化:把我们的数据转化为别人能够识别的数据
反序列化:把别人提供的数据转换或者还原成我们需要的格式

Django Rest_Framework

核心思想:缩减编写api接口代码

Django REST framework是一个建立在Django基础之上的Web 应用开发框架,可以快速的开发REST API接口应用,REST framework还提供了认证、权限、限流、过滤、分页、接口文档等功能支持

特点

提供了定义序列化器Serializer的方法,可以快速根据 Django ORM 或者其它库自动序列化/反序列化;
提供了丰富的类视图、Mixin扩展类,简化视图的编写;
丰富的定制层级:函数视图、类视图、视图集合到自动生成 API,满足各种需要;
多种身份认证和权限认证方式的支持;[jwt]
内置了限流系统;
直观的 API web 界面;
可扩展性,插件丰富CBV

CBV源码分析

》》》路由匹配成功》》》调用as_view方法》》》内部执行了as_view()方法,执行了闭包函数view,得到一个类的实例化对象
》》》在view中调用dispatch方法,先去这个类中没有找到,继续在父类view中找到dispatch方法
》》》getattr做映射》》》执行与请求方式相同的方法》》》最后将requst传入,执行该方法

 APIView的执行流程

1.去除csrf认证
2.包装新的request
    把数据封装在request.data
    reuest>query-PARAMS
    其他和之前一样
3.执行认证、权限、频率
4.全局异常处理

执行流程分析

  请求来了》》》匹配路由》》》路由匹配成功后,开始调用继承apiview的视图类.as_view()》》》在视图类中查找没扎到,到apiview父类中查找,apiview中的as_view调用父类view中的as_view方法,将返回值赋值给apiview中的变量view,所以view就等于父类view中的闭包函数view,而api中的as_view本质是去除csrf认证》》》调用dispatch方法,在视图类中没有

,在apiview中查找到后,dispatch包装一个全新的request赋值给原来的self.request》》》然后执行里面的三大认证》》》反射找到请求方式相同的方法,最后执行此方法,把request传到这个方法中

序列化组件

序列化组件的作用

1.可以序列化
2.可以反序列化
3.反序列化的校验:字段自己,局部钩子,全局钩子

快速使用

1.创建一个py文件,写一个类,继承Serializer
2.在类中写字段
3.在视图类中:实例化得到序列化类的对象:多条,many
4.序列化:序列化类的对象.data  retrun Response(ser.data)

常用字段

跟models中之前学过的有对应关系
ListField   DictField  》》》序列化和反序列化都会用

字段参数

限制反序列化校验字段自己规则的
read_only  write_only:控制字段只做序列化或反序列化的,如果不写就是
    

使用序列化类做反序列化

新增
        ser=BookSerializer(data=request.data)
        ser.is_valid(raise_exception=True)--->只要校验不通过,直接抛异常
        ser.save()  # 继承Serializer,需要在序列化类中重写create方法,完成新增
        序列化类中重写create方法
        def create(self, validated_data):
            # validated_data 前端传入,校验过后的数据
            # 新增一个对象
            return  新增的对象  # 后续再视图类中只要调用ser.data,这里必须返回
    
    修改
    ser=BookSerializer(instance=要修改的对象,data=request.data)
    ser.is_valid(raise_exception=True)--->只要校验不通过,直接抛异常
    ser.save()  # 继承Serializer,需要在序列化类中重写update方法,完成修改
    序列化类中重写update
    def update(self, instance, validated_data):
        # instance 要修改的对象,哪里来的?BookSerializer(instance=要修改的对象的id,data=request.data)
        # validated_data:校验过后数据
        res=Book.objects.filter(pk=instance).update(**validated_data)
        return res   # 返回的res最后干啥了?只要在  视图类中 调用ser.data,他会根据这个返回值做序列化

反序列化校验

1.字段自己
2.局部钩子--》序列化类中写  validate_字段名  传参数
3.全局钩子---》序列化类中写  validate       传参数,字典
        登录接口

定制返回格式

source:1 改名  2 跨表查  3 拿表模型中的方法
    SerializerMethodField:在序列化类中写
        publish=serializers.SerializerMethodField(read_only)
        配合一个 get_username(self,obj)的方法,返回什么,这个字段就是什么
    
    在表模型中写:方法
        publish=serializers.DictField()
    
    只能做序列化用了,反序列化得单独用---》需要使用read_only和write_only控制

 

ModelSerializer使用

class Meta:
        model=表名
        fields=[需要序列化或反序列化的字段,表中没有也要写]
        extra_kwargs={} # 传入字段参数
    重写字段
    
    大部分情况下不需要写create和update了
    
    局部,全局钩子跟之前一模一样

视图组件

两个视图基类

    APIVIew
        类属性
            renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
            parser_classes = api_settings.DEFAULT_PARSER_CLASSES
            authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
            throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
            permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
    GenericAPIView:要使用序列化类,数据库打交道,就可以继承它
        queryset = None
        serializer_class = None
        lookup_field = 'pk'
        filter_backends = api_settings.DEFAULT_FILTER_BACKENDS
        pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
get_queryset(self) #获取所有要序列化的数据,在里面拿到qs对象后要 .all()
        get_object  # 获取单个对象
        get_serializer()--->内部调用了get_serializer_class--》最终返回序列化类的对象,传入要传的参数---》instance ,data  many
        
        filter_queryset---》给ListModelMixin用了--》把配置的filter_backends 依次执行完成过滤

五个扩展类,需要搭配genericAPIView

ListModelMixin,
CreateModelMixin,
UpdateModelMixin,
DestroyModelMixin,
RetrieveModelMixin
    一个视图类中写四个接口--》必须借助于ViewSetMixin
class BookView(ViewSetMixin,GenericAPIView,ListModelMixin,CreateModelMixin,RetrieveModelMixin,DestroyModelMixin):
    queryset = None
    serializer_class = None

九个视图子类

ListAPIView, 
CreateAPIView
RetrieveAPIView,
DestroyAPIView, 
UpdateAPIView
其余四个都是上面五个的组合

 

视图集

-ModelViewSet:重写方法实现你想要的功能
    -ReadOnlyModelViewSet
    -ViewSetMixin:路由写法变了
    -ViewSet:ViewSetMixin+APIView
    -GenericViewSet:ViewSetMixin+GenericAPIView

请求与响应

请求

    -请求源码:request对象
        -request.data
        -request.query_params
        -跟之前一样
        -request._request
        -__getattr__
    -请求能解析编码格式:parser_classes
        -局部使用
        -全局使用

响应

响应Response  源码
        -data:响应体的内容,序列化后的数据给了他
        -headers:响应头    django原生响应头  响应对象['xx']=xxx
        -status:响应状态码
    -响应编码格式--》浏览器,postman,看到的样子
        -局部和全局配置

路由组件

 1 只要继承ViewSetMixin及其子类,路由写法就变了
    -方式一:映射方式
        视图类.as_view({'get':'lqz'})
    -方式二:自动生成
        -SimpleRouter  DefaultRouter
2 action装饰器
参数:methods  detai

认证权限频率

认证的使用

1 写个类,继承BaseAuthentication
2 重写autenticate
3 取出用户传入的 token  ---》通过token能知道是谁
4 认证通过取出用户,认证失败,抛出异常
5 return 查到的对象,token---》后续再request.user中就是当时返回的第一个值
6 视图类中配置
7 全局配置

权限类

1 写个类,继承BasePermission
2 has_permission
3 判断用户的权限  
        acl 权限,取出当前用户所有权限,判断当次请求是否在权限中
        rbac,根据当前用户取出所有角色,通过角色取出所有权限,去个重,判断是否在权限中
4 有权限返回True,没有返回False
5 视图类中配置
6 全局配置

频率类

1 写个类,继承SimpleRatethrottle
2 重写get_cache_key 返回值 唯一的  ip,userid
3 类属性  scope='字符串'  
4 配置文件配置 
    'DEFAULT_THROTTLE_RATES': {
        '字符串': '3/m',
    },
5 视图类中配置
6 全局配置

为什么我们写了 权限类,配置行,它就会执行权限控制?

-APIView 的dispatch中执行了3大认证---def dispatch(self, request, *args, **kwargs):
         self.initial(request, *args, **kwargs) # 三大认证
        
        
    - self.initial   需要从根上
      def initial(self, request, *args, **kwargs):
        self.perform_authentication(request)
        self.check_permissions(request) # 权限类的执行位置
        self.check_throttles(request)
        
    -self.check_permissions(request)
      def check_permissions(self, request):
        for permission in self.get_permissions(): # 你配置在视图类上一个个权限类的对象列表 [权限对象1,权限对象2]
            if not permission.has_permission(request, self): # self,是视图类的对象,因为在APIView中
                self.permission_denied(
                    request,
                    message=getattr(permission, 'message', None),
                    code=getattr(permission, 'code', None)
                )
                
    - def get_permissions(self):
        return [permission() for permission in self.permission_classes]

 认证类源码

-APIView 的dispatch中执行了3大认证---def dispatch(self, request, *args, **kwargs):
         self.initial(request, *args, **kwargs) # 三大认证
        
        
    - self.initial   需要从根上
      def initial(self, request, *args, **kwargs):
        self.perform_authentication(request)# 认证类的执行位置
        self.check_permissions(request) 
        self.check_throttles(request)
        
   - def perform_authentication(self, request):
        request.user
   -去Request类中找user---》方法包装成了数据属性
        @property
        def user(self):
            if not hasattr(self, '_user'):
                with wrap_attributeerrors():
                    self._authenticate()
            return self._user
        
    -去Request类中找self._authenticate()
        def _authenticate(self):
            for authenticator in self.authenticators: # 配置在视图类上一个个认证类的对象列表
                try:
                    # 调用认证类对象的authenticate方法,传入 self,是request对象
                    user_auth_tuple = authenticator.authenticate(self) # 当前登录用户,token
                except exceptions.APIException:
                    self._not_authenticated()
                    raise

                if user_auth_tuple is not None:
                    self._authenticator = authenticator
                    #self就是request对象,后续 request.user就是认证类返回的第一个参数
                    self.user, self.auth = user_auth_tuple  # 解压赋值
                    return

            self._not_authenticated()
            
     -认证类可以配置多个,但是如果有一个返回了,后续的就不走了
    
    -self.authenticators 是request对象的属性,是在Request实例化的时候传入的,它什么时候实例化的,包装新的Reqeust时传入的---》APIView的dispatch--》

http与https之间的区别

1、HTTPS协议需要到CA申请证书,一般免费的证书比较少,因而需要一定费用。

2、HTTP是超文本传输协议,信息是明文传输,HTTPS则是具有安全性的SSL加密传输协议。

3、HTTP和HTTPS使用的是完全不同的链接方式,用的端口也不一样,前者是80端口,后者是443端口。

4、HTTP的链接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比HTTP协议安全。

GET 和POST请求方法的区别

1、post请求更安全;post请求不会作为url的一部分,不会被缓存、保存在服务器日志、以及浏览器浏览记录中,get请求的是静态资源,则会缓存,如果是数据,则不会缓存。
2、post请求发送的数据更大,get请求有url长度限制。
3、post请求能发送更多的数据类型,get请求只能发送ASCII字符。
4、传参方式不同。
5、get产生一个TCP数据包;post产生两个