DRF路由、认证、权限、频率

Posted on   呱呱呱呱叽里呱啦  阅读(34)  评论(0编辑  收藏  举报

DRF路由、认证、权限、频率

路由

原来直接在urls.py中直接.as_view()即可

现在

# 一旦视图类继承了ViewSetMixin,则要在路由中配置actions函数

继承了ModelViewSet的视图类

# 自动配置路由
from rest_framework import routers
router = routers.SimpleRouter() # SimpleRouter只会生成两条url
router.register('books','views.BookViewSet') # router.register('前缀','继承自ModelViewSet的视图类','别名')

urlpatterns += router.urls

# 另有
router = routers.DefaultRouter() # DefaultRouter会生成六条url

action的使用

from rest_framework.decorators import action
class BookModelViewSet(ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    @action(methods=['get',],detail=False) # 向'/get_2/'后缀发送列表中注册的请求时会执行下面函数
    def get_2(self,request):
        book = self.get_queryset()[:2]
        ser = self.get_serializer(book,many=True)
# 如果detail=True,则生成的路由中配置了有名分组pk,需要'/1/get_2'类似的请求,且函数应添加形参pk

认证

# 认证的实现
'''
1.写一个类,继承BaseAuthentication类
from rest_framework.authentication import BaseAuthentication
2.重写authenticate方法,内有认证逻辑,认证通过返回两个值一个值给request.user,另一个值给request.auth,认证失败,抛出AuthenticationFailed异常
3.
'''

源码

# APIView>dispatch>self.initial
self.perform_authentication(request) # >return request.user
class Request # 
    @property
    def user(self):
        self._authenticate()
_authenticate():
    for authenticator in self.authenticators: # 循环自定义配置的认证类(列表)的认证对象列表
        user_auth_tuple = authenticator.authenticate(self) # 这里就用了自己重写的authenticate方法

写认证类

# 应用内新建python文件
from rest_framework.authentication import BaseAuthentication


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

认证类的使用

# 全局使用
from app01.Myauth import MyAuthentication
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'MyAuthentication',

    ],
}
# 在具体视图类中定义authentica_classes为空列表可以局部禁用

# 局部使用
# 在视图类中定义authentication_classes=[]

权限

源码

# APIView>dispatch>self.initial>self.check_permissions(request)

权限的使用

# 定义权限类
from rest_framework.permissions import BasePermission
class UserAdminPermission(BasePermission):
    def has_permission(self, request, view):
        user = request.user
        # print(user.get_permissions_display())
        if user.permissions == 1:
            return True
        else:
            return False

# 局部使用
class NewBooksView(ListAPIView, CreateAPIView):
    permission_classes = [UserAdminPermission]
    queryset = Book.objects.all()
    serializer_class = NewBookModelSerializer

# 全局使用
REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'app01.123.UserAdminPermission',

    ],
}

# 局部禁用
permission_classes = []

内置权限

from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAdminUser

class NewBooksView(ListAPIView, CreateAPIView):
    authentication_classes = [SessionAuthentication]
    permission_classes = [IsAdminUser]
    queryset = Book.objects.all()
    serializer_class = NewBookModelSerializer

频率

内置频率

# 全局使用
REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES': ['rest_framework.throttling.AnonRateThrottle'],
    'DEFAULT_THROTTLE_RATES': {
        'anon':'3/m', # 限制匿名用户每分钟3次访问
    }
}
# 局部使用
REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_RATES': {
        'anon':'3/m', # 限制匿名用户每分钟3次访问
    }
}
class NewNewBooksView(ListAPIView, CreateAPIView):
    authentication_classes = [AnonRateThrottle]

    queryset = Book.objects.all()
    serializer_class = NewBookModelSerializer

# 局部禁用
class NewNewBooksView(ListAPIView, CreateAPIView):
    authentication_classes = []

# 如果要使用内置登录用户频率限制,则作用的也只是auth_user

频率限制

# 新建频率类继承SimpleRateThrottle以重写其内部的get_cache_key方法,并标明配置名称
from rest_framework.throttling import SimpleRateThrottle

class MyThrottle(SimpleRateThrottle):
    scope = 'xxx'
    def get_cache_key(self, request, view):# return结果是频率限制的key
        return request.META.get('REMOTE_ADDR')

# 局部配置或者全局配置频率类
class BookView(ListAPIView):
    throttle_classes = [MyThrottle]
    queryset = models.Book.objects.all()
    serializer_class = BookModelSerializer
    pagination_class = MYLimitOffsetPagination
# 全局配置对应名称的频率值限制
REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_RATES': {
        'xxx': '3/m',
    },
}

自定义频率

from rest_framework.throttling import BaseThrottle
# 自定义频率类,需要重写两个方法,即allow_request、wait
class IPThrottle(BaseThrottle):
    visit_dict = {}
    def __init__(self):
        self.history_list = []
    def allow_request(self, request, view):
        ip = request.META.get('REMOTE_ADDR')
        ctime = time.time()
        if ip not in self.visit_dict:
            self.visit_dict[ip] = [ctime,]
            return True
        self.history_list = self.visit_dict[ip]
        while True:
            if ctime-self.history_list[-1]>60:
                self.history_list.pop()
            else:
                break
        if len(self.history_list)<2: # 配置一个周期内的频次限制
            self.history_list.insert(0,ctime)
            return True
        else:
            return False
    def wait(self):
        ctime = time.time()
        return 60 - (ctime-self.history_list[-1])

from utils.throttle1 import IPThrottle
class BookView(ListAPIView):
    throttle_classes = [IPThrottle]
    queryset = models.Book.objects.all()
    serializer_class = BookModelSerializer
    pagination_class = MYLimitOffsetPagination
(评论功能已被禁用)
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示