学无先后,达者为师

网站首页 编程语言 正文

Django-认证-权限控制-节流-分页-过滤

作者:lonely-hermit 更新时间: 2022-05-13 编程语言

简单来讲,认证确定了你是谁

权限确定了你能不能访问某个接口

限制确定了你访问某个接口的最高频率

一、认证

身份验证是将传⼊请求与⼀组标识凭据(例如请求来⾃的⽤户或其签名的令牌)相关联的机制。然后权限和限制组件决定是否拒绝这个请求。认证本身不会允许或拒绝传⼊的请求,它只是简单识别请求携带的凭证。

REST framwork不仅自己有着开箱即用的验证方案,还允许你自己实现验证方案

1.1、自定义认证

要实现⾃定义的认证⽅案,要继承BaseAuthentication类并且重 写.authenticate(self, request) ⽅法。如果认证成功,该⽅法应返回(user, auth)的 ⼆元元组,否则返回None,还可以抛出AuthenticationFailed异常

在App下,创建authentications.py,然后⾃定义认证类

from django.core.cache import cache
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed

from app.models import Students


class appAuthentication(BaseAuthentication):
    def authenticate(self, request):
        token = request.query_params.get('token')
        if not token:
            raise AuthenticationFailed('没有 token')
        username = cache.get(token)
        if not username:
            raise AuthenticationFailed('token 过期')
        try:
            student = Students.objects.filter(stu_name=username)
            if student:
                return student, None
            else:
                return None
        except Exception as e:
            print(e)
            raise AuthenticationFailed('token 不合法')

urls.py

urlpatterns = [
    path('getToken/', views.getToken.as_view(), name='getToken'),

    path('testToken/',views.testToken.as_view(),name='testToken'),
]

views.py

class getToken(APIView):
    # 我们的get请求直接给前端一个token,用于测试
    def get(self, request):
        username = '123'
        token = token_confirm.generate_validate_token(username=username)
        mycache = cache.get(token)
        if mycache:
            token = mycache
        else:
            cache.set(token, token, settings.CACHE_TIMEOUT)
        return HttpResponse('http://127.0.0.1:8000/testToken?token=' + token)

class testToken(APIView):
    authentication_classes = (appAuthentication,)

    def get(self,request):
        return HttpResponse('OK')

我们访问getToken可以得到需要验证的网址,然后这个网址登录可以看到我们登录后返回的信息,OK

我们也可以进行全局级别的认证,只是这样的话需要我们配置一下

settings.py

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'App.authentications.MyAuthentication', 
    )
}

二、权限控制

权限控制可以限制⽤户对于视图的访问和对于具体数据对象的访问

在执⾏视图的dispatch()⽅法前,会先进⾏视图访问权限的判断

在通过get_object()获取具体对象时,会进⾏对象访问权限的判断

2.1、系统内置的权限

AllowAny 允许所有⽤户

IsAuthenticated 仅通过认证的⽤户

IsAdminUser 仅管理员⽤户

IsAuthenticatedOrReadOnly 认证的⽤户可以完全操作,否则只能get读取

2.2、自定义权限控制

我们自己写一个permission.py

# 写⼀个继承⾃BasePermission
class WomanPerssion(BasePermission):
    # 复写⾥⾯的has_permission函数
    def has_permission(self, request, view):
        # request.user是认证后拿到的元组第一个值
        print(request.user)
        if request.user != None:
            # 判断当前⽤户是不是女性用户
            return request.user.stu_gender == 'w'
        	# 返回True就是验证通过,返回False就是验证失败
        return False

我们的视图函数只需要再加一句话

class testToken(APIView):
    authentication_classes = (appAuthentication,)
    permission_classes = (WomanPerssion,)

    def get(self, request):
        return HttpResponse('OK')

如果要进行全局的验证的话

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'App.authentications.MyAuthentication', 
    ),
    "DEFAULT_PERMISSION_CLASSES":
        ["app.permission.WomanPerssion",]
}

三、节流器

节流类似于权限,⽤于控制客户端可以对API发出的请求的速率

mythrottle.py

from rest_framework.throttling import SimpleRateThrottle


class VisitThrottle(SimpleRateThrottle):
    # 转换频率每分钟5次,转换频率 = num/duration,其中duration可以是s(秒)、m(分)、h(⼩时)、d(天)
    rate = '5/m'
    score = 'vistor'

    # 返回⼀个唯⼀标示⽤以区分不同的⽤户
    def get_cache_key(self, request, view):

        return self.get_ident(request)  # 返回⽤户i

视图级别的控制

class testToken(APIView):
    authentication_classes = (appAuthentication,)
    permission_classes = (WomanPerssion,)
    throttle_classes = (VisitThrottle,)

    def get(self, request):
        return HttpResponse('OK')

全局的控制

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'App.authentications.MyAuthentication', 
    ),
    "DEFAULT_PERMISSION_CLASSES":
        ["app.permission.WomanPerssion",],
    'DEFAULT_THROTTLE_CLASSES': ['apps.mythrottle.VisitThrottle'],
    'DEFAULT_THROTTLE_RATES': {
         'vistor': '3/m',
         'anon': '10/day',# 匿名⽤户
   }
}

DEFAULT_THROTTLE_RATES 可以使⽤ second , minute , hour 或 day 来指明周期

3.1、可选限流器

3.1.1、AnonRateThrottle

限制所有匿名未认证⽤户,使⽤IP区分⽤户。使⽤ DEFAULT_THROTTLE_RATES[‘anon’] 来设置频次

3.1.2、UserRateThrottle

限制认证⽤户,使⽤User id 来区分。 使⽤ DEFAULT_THROTTLE_RATES[‘user’] 来设置频次

3.1.3、ScopedRateThrottle

限制⽤户对于每个视图的访问频次,使⽤ip或user id

eg:

class ContactListView(APIView):
    throttle_scope = 'contacts'
    
REST_FRAMEWORK = {
     'DEFAULT_THROTTLE_CLASSES': (
     'rest_framework.throttling.ScopedRateThrottle',
     ),
     'DEFAULT_THROTTLE_RATES': {
     	'contacts': '1000/day',
     	'uploads': '20/day'
     }
}

四、分页Pagination

REST framework提供了分⻚的⽀持。 我们可以在配置⽂件中设置全局的分⻚⽅式

REST_FRAMEWORK = {
	'DEFAULT_PAGINATION_CLASS':'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 10 # 每⻚数⽬
}

4.1、自定义分页类

也可通过⾃定义Pagination类,来为视图添加不同分⻚⾏为。在视图中通过 pagination_clas 属性来指明

注意:如果在视图内关闭分⻚功能,只需在视图内设置

pagination_class = None

4.2、PageNumberPagination

前端访问形式GET http://127.0.0.1:8000/studentView/?page=1

可以在⼦类中定义的属性:
page_size 每⻚数⽬
page_query_param 前端发送的⻚数关键字名,默认为"page"
page_size_query_param 前端发送的每⻚数⽬关键字名,默认为None
max_page_size 前端最多能设置的每⻚数量

serializer.py

from rest_framework import serializers
from app.models import Students


class studentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Students
        # 包含模型中所有字段
        fields = '__all__'

models.py

class Students(models.Model):
    stu_num = models.CharField(primary_key=True, max_length=8)
    stu_name = models.CharField(max_length=40)
    stu_gender = models.CharField(max_length=4)
    stu_age = models.IntegerField()
    cid = models.ForeignKey(Classes, models.DO_NOTHING, db_column='cid', blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'students'

urls.py

urlpatterns = [
    path('studentView/', views.studentView.as_view(), name='studentView'),
]

views.py

class studentView(ListAPIView):
    queryset = Students.objects.all()
    serializer_class = studentSerializer
    pagination_class = studentPagination

pagination.py

from rest_framework.pagination import PageNumberPagination

class studentPagination(PageNumberPagination):
    page_size_query_param = 'page_size'
    max_page_size = 1
    page_size = 1
    page_query_param = 'pagepage'

我们再前端访问就可以得到我们的数据了

4.3、LimitOffsetPagination

前端的访问形式GET http://127.0.0.1:8000/studentView/?limit=100&offset=400

可以在⼦类中定义的属性: 
default_limit 默认限制,默认值与 PAGE_SIZE 设置⼀直 
limit_query_param limit参数名,默认'limit' 
offset_query_param offset参数名,默认'offset' 
max_limit 最⼤limit限制,默认None

他的设置方法和前面的一致

五、过滤

对于列表数据可能需要根据字段进⾏过滤,我们可以通过添加django-fitlter扩展来增强⽀持。官⽹地址:https://django-filter.readthedocs.io/en/master/index.html

5.1、安装

pip install django-filter

5.2、配置

settings.py

INSTALLED_APPS = [
    'django_filters', # 需要注册应⽤,
]
REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
}

5.3、视图设置

class studentView(ListAPIView):
    queryset = Students.objects.all()
    serializer_class = studentSerializer
    filter_fields = ('stu_name', 'stu_gender')

其他的和上面的保持一致,我们访问下面这个地址

GET http://127.0.0.1:8000/studentView/?stu_gender=w

5.4、自定义过滤类

customfilter.py

import django_filters
from django_filters import rest_framework as filters
from app.models import Students


class studentsFilters(django_filters.FilterSet):
    class Meta:
        # field_name = "bread" 模型中的字段名; lookup_expr是运算,gte表示 >=
        min_read = filters.NumberFilter(field_name="bread", lookup_expr='gte')
        ax_read = filters.NumberFilter(field_name="bread", lookup_expr='lte')
        model = Students
        fields = {
            'stu_age': ['icontains'],  # 键是字段名,列表⾥是查询进⾏运算
        }

views.py

class studentView(ListAPIView):
    queryset = Students.objects.all()
    serializer_class = studentSerializer
    filter_class = studentsFilters  # 指定过滤类
  • field_name 数据库中字段名
  • lookup_expr 操作(和django的orm中运算符⼀样) 关系运算符:gte(>=) 、gt(>)、 lte(<=)、 lt(<) 字符串; icontains(忽略⼤⼩写,包含)
  • model指定模型
  • fields可以指定过滤字段

访问测试:

http://127.0.0.1:8000/studentView/?stu_gender=w

http://127.0.0.1:8000/studentView/?minage=0&maxage=2

这个其实并不重要,我们可以直接数据查询返回

六、自动生成接口文档

6.1、安装

pip install coreapi

6.2、配置

settings.py

REST_FRAMEWORK = {
    'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema'
}

6.3、设置接⼝⽂档访问路径

在总路由中添加接⼝⽂档路径。

⽂档路由对应的视图配置为 rest_framework.documentation.include_docs_urls ,

参数 title 为接⼝⽂档⽹站的标题

6.4、文档描述说明定义

6.4.1、单一方法视图

单⼀⽅法的视图,可直接使⽤类视图的⽂档字符串,如

class BookListView(generics.ListAPIView):
    """
    返回所有图书信息.
    """
6.4.1、多个方法视图
class BookListCreateView(generics.ListCreateAPIView):
     """
     get:
     返回所有图书信息.
     post:
     新建图书.
     """
6.4.3、视图集

对于视图集ViewSet,仍在类视图的⽂档字符串中分开定义,但是应使⽤action 名称区分,

class BookInfoViewSet(mixins.ListModelMixin,mixins.RetrieveModelMixin, GenericViewSet):
     """
     list:
     返回图书列表数据
     retrieve:
     返回图书详情数据
     latest:
     返回最新的图书数据
     read:
     修改图书的阅读量
     """
6.4.4、网址访问

http://127.0.0.1:8000/docs/

原文链接:https://blog.csdn.net/weixin_43903639/article/details/122991938

栏目分类
最近更新