认证类和频率类

认证类

1.认证类编写

创建新的.py文件

from .models import User, Token
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed

class LoginAuth(BaseAuthentication):
    def authenticate(self, request):

        # 从请求中获取token
        token = request.query_params.get('token')
        # 查询token是否存在
        user_token = Token.objects.filter(token=token).first()

        if user_token:

            # 说明用户存在,还回登录用户和token
            """ 固定还回这两个值 """
            return user_token.uId, token

        else:
            # 如果用户未登录,报异常
            raise AuthenticationFailed('小伙子,你没有登录,不能访问!')

2.认证类使用

在需要认证的视图类中注册

# 首先导入认证类
from .auth import LoginAuth

# 局部使用
    class BookView(APIView):
        authentication_classes = [LoginAuth, ]

# 局部禁用
     class BookView(APIView):
         authentication_classes = []

# 全局使用
REST_FRAMEWORK = {
                    'DEFAULT_AUTHENTICATION_CLASSES':['app01.auth.LoginAuth',]
                 }

权限类

1.权限类编写

from rest_framework.permissions import BasePermission

class PermissionAuth(BasePermission):

    # 1.自定义还回提示信息
    # 2.修改配置之文件(setting.py)
    message = '你没有权限'

    def has_permission(self, request, view):

        # 一. user_type 是在表模型自定义的字段。
        # 下面代码查询user时,可能因为用户未登录,出现错误,可以使用异常捕获处理,还回 False.(表示无权限)。
        if request.user.user_type == 1:

            # 还回布尔值
            return True

        else:

            # 二. get_user_type_display() ===> get_字段名_display() 获取选择序号所对应的中文
            # 三. user_type  获取序号
            # 《一,二,三,不明白的话可以看下面的图》
            self.message = f'{request.user.get_user_type_display()}, 你当前没有权限'

            # 还回布尔值
            return False

image

2.权限类使用

在需要认证的视图类中注册

# 首先导入权限类
from .auth import PermissionAuth

# 局部使用
    class BookView(APIView):
        permission_classes = [PermissionAuth,]

# 局部禁用
     class BookView(APIView):
         permission_classes = []

# 全局使用
REST_FRAMEWORK = {
                    'DEFAULT_PERMISSION_CLASSES':['app01.auth.PermissionAuth',]
                 }

频率类

1.内置方法

(1)频率类步骤

 -第一步: 写一个类,继承SimpleRateThrottle
 -第二步: 重写get_cache_key方法
 -第三步: return 一个返回值 =====》 返回什么,就以什么做限制
 -第四步: 写一个类属性
     # 配置 scope 需要执行第五步的配置。
     scope = 'lqz'
     或
     # 配置 rate 就不用执行第五步的配置。
     rate = '5/minute'
 -第五步:配置文件中配置
     REST_FRAMEWORK = {
         "DEFAULT_THROTTLE_RATES": {
             # 第四步中 scope 对应的值
             'lqz':'3/m'   # 数字/s m h  d ====》  每时间内可以触发 n 次
          },
     }


-第六步:局部和全局使用
     局部使用:视图类中
         class BookView(APIView):
             throttle_classes = [IPThrottle, ]

     全局使用:配置文件
         REST_FRAMEWORK = {
             "DEFAULT_THROTTLE_RATES": {
                 # 频率类中scope对应的值
                 'lqz': '3/m'  # 数字/s m h  d
             },
             'DEFAULT_THROTTLE_CLASSES':['app01.throttling.IPThrottle',]
         }

(2)频率类编写

from rest_framework.throttling import SimpleRateThrottle

class IPThrottle(SimpleRateThrottle):
    scope = '5_min'
    或
    rate = '5/minute'

    def get_cache_key(self, request, view):

        # 如果未登录,request.user值为None,此类不生效
        print(request.user.id)

        # 此类还回什么,就以什么做限制
        # eg: 以 "用户" 做限制,那就返回 user.id
        #     以 "ip" 做限制,那就返回 户端ip地址

        # 获取客户端的地址 request.META.get('REMOTE_ADDR')
        return request.META.get('REMOTE_ADDR')

(3)视图类编写

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

    def get(self, request):
        return Response('ok')


    # 1.配置中文提示信息, 2.配置文件中也行
    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)

2.自定义方法 (继承 BaseThrottle)

(1)频率类编写

from rest_framework.throttling import BaseThrottle
import time

class MyThrittle(BaseThrottle):
    USERIP_TIME = {}
    def __init__(self):

        # 设置默认值,
        self.disiply = None

    # 重写该方法需要还回 True 或 False
    def allow_request(self, request, view):

        # 获取登录用户 ip
        user_ip = request.META.get('REMOTE_ADDR')

        newTime = time.time()

        if user_ip not in self.USERIP_TIME:
            self.USERIP_TIME[user_ip] = [newTime, ]
            return True

        while self.USERIP_TIME[user_ip] and newTime - self.USERIPip_TIME[user_ip][-1] > 10:
            self.USERIP_TIME[user_ip].pop()

        # 用户访问时间数组
        self.disiply = self.USERIP_TIME[user_ip]

        if len(self.USERIP_TIME[user_ip]) < 3:
            self.USERIP_TIME[user_ip].insert(0, newTime)
            return True
        else:
            return False

    # 重写 wait 方法
    def wait(self):

        newTime = time.time()

        # 还回剩余多少秒后可以访问
        return 10 - (newTime - self.disiply[-1])

排序

1..视图类

前提是继承 GenericAPIView 及其子类。

from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin

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


    # """  固定写法  """
    filter_backends = [OrderingFilter, ]
    # 填写需要排序的字段
    ordering_fields = ['price', 'id']

2.路由

from rest_framework.routers import SimpleRouter


router = SimpleRouter()
router.register('book', views.BookView, 'book')

urlpatterns = []

urlpatterns += router.urls

3.访问方式

# 按价格升序排序
http://127.0.0.1:8006/book/?ordering=price

# 按价格降序排序
http://127.0.0.1:8006/book/?ordering=-price

# 按价格升序排序,价格相同则按id升序排序
http://127.0.0.1:8006/book/?ordering=price,id

过滤

1.内置方法

模糊查询,不能指定查询某个字段

(1)视图类

from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin

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

    # 可以添加多个方法
    filter_backends = [SearchFilter, ]
    search_fields = ['name', 'price']

(2)访问方式

http://127.0.0.1:8000/book?search=恋爱大陆

(3)查询方式

search = xx ---->  具体查询是  name like xx or price like xx

2.第三方模块

(1)下载

pip3 install django-filter

(1)视图类

from django_filters.rest_framework import DjangoFilterBackend

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

   filter_backends = [DjangoFilterBackend, ]
   filter_fields = ['name', 'price']

3.自定义过滤器

(1)过滤器类

from rest_framework.filters import BaseFilterBackend

class FilterFields(BaseFilterBackend):

    # 重写 filter_queryset 方法
    def filter_queryset(self, request, queryset, view):

        # 请求中获取过滤字段
        name = request.query_params.get('name')

        # 过滤名字里包含 name(过滤字段)的数据
        queryset = queryset.filter(name__contains=name)

        return queryset

(1)视图类

from .throttling import FilterFields

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

    # 固定写法
    filter_backends = [FilterFields, ]

posted @ 2023-04-07 22:15  codegjj  阅读(5)  评论(0编辑  收藏  举报