Loading

频率类、排序、过滤,http回顾,鸭子类型简述

补充

什么是鸭子类型

-接口概念:规范子类的行为,可以当成:父类有的一些方法--->Duck类--->speak,run方法
-只要子类,继承了Duck,我们就认为,这些子类,他们是用一个类,都是鸭子Duck类
-python不推崇这个,推崇鸭子类型
	只要有一个类中,有speak和run方法,这个类就是鸭子类
    -在python中有两种方式违背了鸭子类型, 但提高了健壮性
    -abc装饰器,装饰父类中的方法,子类必须实现该方法,如果不实现,就抛异常---》正好违背了鸭子类型
    -djagno中常用的方式,父类抛异常的方式,子类必须重写该方法:
       def authenticate(self, request):
        	raise NotImplementedError(".authenticate() must be overridden.")
           

函数书写方式

def add(a:int,b:int):->int  用来提示要传入什么类型的参数,也是为了提高程序的可读性,健壮性
    return a+b

健壮性(鲁棒性)

健壮性:系统在不正常输入情况下仍能表现正常的程度。

    处理未期望的行为和错误终止;
    即使终止执行,也要准确/无歧义地向用户展示错误信息
    错误信息有助于debug
    正确性:程序按照spec加以执行的能力,是最重要的质量指标

正确性 vs 健壮性

    正确性,永不给用户错误的结果;健壮性,尽可能保持软件运行而不是总是退出
    正确性倾向于直接报错,健壮性倾向于容错
    对外的接口,倾向于健壮性;对内的实现,倾向于正确性
原文链接:https://blog.csdn.net/tpc724/article/details/106819441

频率类

# 某个接口,限制访问频率----》可以根据IP,用户id
# 频率类的编写
	-第一步:写一个类,继承SimpleRateThrottle
    -第二步:重写get_cache_key方法
    -第三步:返回什么,就以什么做限制
    -第四步:写一个类属性
    	-scope = '3_min'
    -第五步:配置文件中配置
    	REST_FRAMEWORK = {
            # 频率类中scope对应的值
            '3_min':'3/m'   # 数字/s m h  d
        }
        
   -第六步:局部和全局使用
	局部用:视图类中
    	class BookView(APIView):
    		throttle_classes = [IPThrottle, ]
    全局用:配置文件
    	REST_FRAMEWORK = {
            "DEFAULT_THROTTLE_RATES": {
                # 频率类中scope对应的值
                '3_min': '3/m'  # 数字/s m h  d
            },
            'DEFAULT_THROTTLE_CLASSES':['app01.throttling.IPThrottle',]
        }

使用

频率类

class IPThrottle(SimpleRateThrottle):
    # 写一个类属性,字符串
    scope = '3_min'
    def get_cache_key(self, request, view):
        # return 什么就一什么做限制, 返回ip   返回用户id
        return request.META.get('REMOTE_ADDR')
        # return request.user.id  # 返回用户id

视图类

class BookView(APIView):
    throttle_classes = [IPThrottle, ]

    def get(self, request):
        return Response('ok')
	# 自定义提示信息,固定格式
    def throttled(self, request, wait):
        from rest_framework.exceptions import Throttled
        class MyThrottled(Throttled):
            default_detail = '超限制乐'
            extra_detail_singular = '还有 {wait} 描述.'
            extra_detail_plural = '出了 {wait} 秒.'

        raise MyThrottled(wait)

配置文件

REST_FRAMEWORK = {
    "DEFAULT_THROTTLE_RATES": {
        # 频率类中scope对应的值
        '3_min': '3/m',  # 数字/s m h  d
        'anon':'4/h',
        'user':'5/m'
    },
    'DEFAULT_THROTTLE_CLASSES':['app01.throttling.IPThrottle',]

}

drf内置认证类,权限类,频率类

内置的认证

# 内置的认证---》跟咱们项目都补贴和,咱们不用,咱们自己根据自己的规则写
	-SessionAuthentication:之前老的session认证登录方式用,后期都不用了
    -BasicAuthentication :基本认证方式,咱们不用
    -TokenAuthentication :使用token认证方式,有用,但是咱们也是自己写的

内置的权限类

# 内置的权限类
	-IsAdminUser :校验是不是auth的超级管理员权限
    -IsAuthenticated:后面会用到,验证用户是否登录了,登录了才有权限,没登录就没有权限
    -IsAuthenticatedOrReadOnly:知道有这个东西即可

内置的频率类

# 内置的频率类
	-UserRateThrottle :限制登录用户的频率,需要配置配置文件
    -AnonRateThrottle:登录用户不限制,未登录用户限制,需要配置配置文件

认证类源码分析(了解)

####### 不要无脑按住ctrl建点击查找,因为方法,属性的查找顺序是按照 mro列表查找顺序来的

研究第一个点:三大认证的执行顺序---》入口---》APIView的dispatch中第----》三大认证

-dispatch中第 497行 --》self.initial(request, *args, **kwargs)
    -self是谁?self是个对象,是谁的对象? 是视图类的对象---》BookView这些视图类
    -APIView的initial方法的第414行
        self.perform_authentication(hhrequest)  # 认证
        self.check_permissions(request)     # 权限
        self.check_throttles(request)      # 频率

为什么写了认证类,配置在视图类上,就会走认证?---》入口-->self.perform_authentication(request)

第一步:self.perform_authentication源码

 def perform_authentication(self, request):
     	request.user

第二步:新的request类中 user(属性?方法?)

from rest_framework.request import Request
         @property
        def user(self):
            if not hasattr(self, '_user'):
                with wrap_attributeerrors():
                    self._authenticate()  # 最开始,是没有_user的,执行这句
            return self._user

第三步:self._authenticate() --》self是Request的对象---》Request的_authenticate方法

def _authenticate(self):
    # authenticator配置的认证类的对象
    for authenticator in self.authenticators: # 你配置在视图类上authentication_classes = [你写的认证类,]----》[你写的认证类(),你写的认证类2()]
        try:
            # 调用认证类对象的authenticate方法,传了几个?2个,一个认证类自己,一个是self:Request类的对象
            user_auth_tuple = authenticator.authenticate(self)
        except exceptions.APIException: # 抛的是AuthenticationFailed,捕获的是APIException
            self._not_authenticated()
            raise

        if user_auth_tuple is not None:
            self._authenticator = authenticator
            # 如果返回了两个值,第一个值给了request.user,第二个值给了request.auth
            self.user, self.auth = user_auth_tuple
            return

第四步: self.authenticators到底是啥---》你配置在视图类上authentication_classes = [你写的认证类,]----》[你写的认证类(),你写的认证类2()]

-Reqeust这个类实例化的时候,传入的,如果不传就是空元组
-找Request的实例化---》dispatch中包装了新的Request
    -request = self.initialize_request(request, *args, **kwargs)
    -authenticators=self.get_authenticators(),

-APIView中get_authenticators---》268行
  def get_authenticators(self):
     # self.authentication_classes配在视图类上的认证类列表---》认证类对象列表
    return [auth() for auth in self.authentication_classes]

排序

'''排序功能接口只针对于:获取所有接口'''

# 继承了GenericAPIView的视图类,只要加入,两个类属性
class BookView(GenericViewSet, ListModelMixin):
    serializer_class = BookSerializer
    queryset = Book.objects.all()

    filter_backends = [OrderingFilter, ]
    ordering_fields = ['price','id' ]
# 访问的时候
http://127.0.0.1:8000/api/v1/books?ordering=price  # 按price升序
http://127.0.0.1:8000/api/v1/books?ordering=-price # 按price降序
http://127.0.0.1:8000/api/v1/books?ordering=price,id # 先按价格升序排,价格一样,再按id升序排

过滤

内置的过滤使用

#  查询名字为金金金的所有图书:获取所有接口

# 内置的过滤使用---》不能指定查询那个字段,模糊查询
	-继承了GenericAPIView的视图类,只要加入,两个类属性
    class BookView(GenericViewSet, ListModelMixin):
        serializer_class = BookSerializer
        queryset = Book.objects.all()

        filter_backends = [SearchFilter,]
        search_fields=['name','price']  # 按name或price过滤
	-使用
        http://127.0.0.1:8000/api/v1/books?search=金金金
        # search= xx ----》具体查询是  name like xx or price like xx

第三方过滤模块

# 我们想http://127.0.0.1:8000/api/v1/books?name=金金金&price=12---》第三方django-filter
-安装:pip3 install django-filter

-继承了GenericAPIView的视图类,只要加入,两个类属性
     from django_filters.rest_framework import DjangoFilterBackend
     class BookView(GenericViewSet, ListModelMixin):
        serializer_class = BookSerializer
        queryset = Book.objects.all()
	-使用
    http://127.0.0.1:8000/api/v1/books?name=金金金&price=11

自定义过滤器---》完成更多查询操作

-写一个类,继承BaseFilterBackend
-重写filter_queryset方法
-配置在视图类中
# 自定义过滤类
class MyFilter(BaseFilterBackend):
    def filter_queryset(self, request, queryset, view):
        name = request.query_params.get('name')
        price = request.query_params.get('price')
        book = Book.objects.filter(name__contains=name, price__gt=price)
        return book


from .throttling import FilterName
class BookView(GenericViewSet, ListModelMixin):
    serializer_class = BookSerializer
    queryset = Book.objects.all()

    filter_backends = [FilterName, ]

既有过滤又有排序

class BookView(GenericViewSet, ListModelMixin):
    serializer_class = BookSerializer
    queryset = Book.objects.all()
    filter_backends = [FilterName, OrderingFilter]
    ordering_fields = ['price', ]

源码分析,为什么这么配置就生效

-GenericAPIView的方法
def filter_queryset(self, queryset):
    for backend in list(self.filter_backends):
        queryset = backend().filter_queryset(self.request, queryset, self)
    return queryset

回顾

# http回顾
	-http 请求:特点
     -1 http基于tcp之上的协议---》tcp处于 osi七层的传输层  http是处于应用层
     -2 基于请求响应  必须是客户端发起请求,服务端响应,不能服务端主动推送消息
     -3 无状态,无连接  cookie和session
    -http协议有版本
    	-0.9  1.1  2.x:多路复用   3.x 
    -http分请求协议和响应协议
    	-请求协议
        	-请求首行:请求方式,请求地址(get地址中数据),协议版本
            -请求头:key:value  客户端类型,客户端ip地址,请求编码,cookie。。。。
            -请求体:所谓的body体,post,put请求真正携带的数据
            	-urlencoded:  name=lqz&age=19&gender=male
                -json :   {"name":"lqz","age":19,"gender":"male"}
                -form-data: 两部分:数据部分,文件部分中间用  -----------分割
    	-响应协议
        	-响应首行:协议版本,响应状态码,响应状态短语
            -响应头:响应编码格式,cookie。。。
            -响应体:html,json,xml。。。。
  
posted @ 2022-06-26 14:55  香菜根  阅读(132)  评论(0编辑  收藏  举报