4.DRF 权限&访问频率&过滤&排序

0. 准备环境

* 1. 创建项目

image-20220420183601918

* 2. 注册rest_framework
INSTALLED_APPS = [
    ...
    'rest_framework'
]
* 3. 创建表三张表
from django.db import models


# Create your models here.

# 用户表
class User(models.Model):
    # 用户名称
    username = models.CharField(max_length=32)
    # 用户密码
    password = models.CharField(max_length=32)
    # 身份标识
    identity = models.IntegerField(choices=((1, '小米1'), (2, '小米2'), (3, '小米3')))


# token表
class Token(models.Model):
    # token值
    value = models.CharField(max_length=64)
    # 外键管理用户viands
    user = models.OneToOneField(to=User)


# 书籍表
class Book(models.Model):
    # 书名
    title = models.CharField(max_length=32)
    # 价格
    price = models.CharField(max_length=32)
    # 作者
    author = models.CharField(max_length=32)
    # 出版社
    publish = models.CharField(max_length=32)
python manage.py makemigrations
python manage.py migrate
为用户表添加数据

image-20220420191720206

使用ModelViewSet快速定义5个接口
* 4. 自动生成路由
from django.conf.urls import url
from django.contrib import admin

# 导入生成路由模块
from rest_framework import routers

# 导入视图层
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
]

# 生成简单路由对象
router_obj = routers.SimpleRouter()

# 生成books api接口
router_obj.register('api/books/v1', views.BookModelViewSet1)

# 将路由添加到路由列表中
urlpatterns += router_obj.urls
* 5. 定义模型序列化器
# 导入模型序列化器
from rest_framework import serializers
# 导入模型层
from app01 import models


# 定义模型序列化器
class BookModelSerializers(serializers.ModelSerializer):
    # 定义Meta类
    class Meta:
        # 使用的表
        model = models.Book
        # 序列化的字段
        fields = '__all__'

* 6. 定义视图类
from django.shortcuts import render

# Create your views here.

# 导入视图集
from rest_framework.viewsets import ModelViewSet
# 导入模型层
from app01 import models
# 导入模型序列化器
from app01.serializer import BookModelSerializers


# 书籍API
class BookModelViewSet1(ModelViewSet):
    # 获取表中所有的模型对象
    queryset = models.Book.objects.all()
    # 使用的序列化器
    serializer_class = BookModelSerializers
* 7. 登入功能路由
    # 登入校验路由
    url(r'^login/', views.Login.as_view())
* 8. 登入校验视图类
# 导入APIView
from rest_framework.views import APIView
# 导入响应对象
from rest_framework.response import Response

# 导入随机字符串
import uuid


# 登入功能
class Login(APIView):
    # 定义登入方法
    def post(self, request):
        # 获取request中用户提交的数据去用户表中校验
        username = request.data.get('username')
        password = request.data.get('password')
        # 判断用户名称或用户密码是否为空
        if not (username and password):
            return Response({
    
    'code': 101, 'msg': '用户名称或密码不能为空!'})

        # 去数据库中校验
        user_obj = models.User.objects.filter(username=username, password=password).first()
        # 判断检验结果
        if not user_obj:
            return Response({
    
    'code': 102, 'msg': '用户名称或密码不正确!'})

        # 生成token值
        value = uuid.uuid4()
        # 将token值存入数据表中, 没有则创建有则更新
        models.Token.objects.update_or_create(defaults={
    
    'value': value}, user=user_obj)

        # 返回token值
        return Response({
    
    'code': 200, 'msg': '验证成功!', 'token': value})
* 9. 测试

* 10 认证类
# 导入认证类
from rest_framework.authentication1 import BaseAuthentication
# 导入模型层
from app01 import models
# 导入异常模块
from rest_framework.exceptions import AuthenticationFailed


# 定义认证类
class LoginAuthentication(BaseAuthentication):
    # 校验方法
    def authenticate(self, request):
        # 获取request中携带的token值
        token = request.data.get('token')
        print(token)
        # 没有token值, 抛异常
        if not token:
            raise AuthenticationFailed('没有携带token值!')

        # 去数据库中校验
        token_obj = models.Token.objects.filter(value=token).first()
        # 判断校验是否成功
        if not token_obj:
            raise AuthenticationFailed('校验失败!')

        # 校验成功, 返回两个数据
        return token_obj.user, token
* 11. 登入认证
# 全局登入校验
REST_FRAMEWORK = {
    
      
    'DEFAULT_AUTHENTICATION_CLASSES': ['books_msg.authenticates.LoginAuthentication', ]
}
# 为登入功能设置局部不校验, 不设置就没法登入了.

# 登入功能
class Login(APIView):
    # 登入不校验token
    authentication_classes = []
    ...
* 12 校验

image-20220420222712441

1. 权限认证

权限(Permissions): 可以限制用户对于视图的访问和对具体数据的操作.
权限认证一定是在经过登入认证, 才能进行权限认证, 权限认证默认所有的用户访问都允许.
登入认证将将用户数据对象返回, 被request.user接收, 权限认证再将用户的数据对象取出来做权限的判断.
在dispatch方法中执行请求方法前, 会先进行视图访问权限判断
在通过get_object()获取具体对象时, 会进行模型对象访问权限的判断.

2022-04-20_00247

1.1 源码

APIView的dispatch方法中,视图类对象触发initial()方法.
self.check_permissions(request)
    def check_permissions(self, request):
        """
        Check if the request should be permitted.
        Raises an appropriate exception if the request is not permitted.
        """
        # 遍历类别拿出一个个的权限对象
        for permission in self.get_permissions():  # 权限类对象, 可以有多个, 存放在列表中
            # 执行权限对象的has_permission方法, 返回值为True则认证通过,什么都不做
            if not permission.has_permission(request, self):
                # 权限认证不通过执行permission_denied方法, 
                self.permission_denied(
                    request, message=getattr(permission, 'message', None)
                )
permission.has_permission(request, self), 
has_permission接收了三个参数, 第一个permission, 权限类对象self, request对象, self视图类对象.

image-20220420171220841

2022-04-20_00249

在自定义的视图类中定义permission_class的属性值, 存放权限类的类名.
如果自己没有定义就会去配置文件中查找...

2022-04-20_00250

1.2 权限类

* 1 新建一个类, 该类继承BasePermission, 类中必须实现has_permission方法, 该方法中写逻辑,
    给权限返回True, 不给权限返回False
局部设置 在类中定义permission_classes
    permission_classes = [权限类] 
局部禁用
    permission_classes = []
全局设置 在settings.py 设置
    REST_FRAMEWORK={
    
    'DEFAULT_PERMISSION_CLASSES': ['权限类地址',], }
# 导入权限基类
from rest_framework.permissions import BasePermission


# 定义权限类
class RootPermission(BasePermission):
    # 定义权限方法
    def has_permission(self, request, view):
        # 将 request.user 中数据对象的身份字段 取出来
        # 取数字
        identity_int = request.user.identity
        #  get_字段_display() 取数字对应的描述值
        identity_str = request.user.get_identity_display()

        print(identity_int, identity_str)

        # 限制只有小米1才能通过,
        if identity_int != 3:
            print('权限认证成功!')
            return True

        else:
            print('没有权限!')
            return False

* 2. 建一个测试数图类
    # 局部权限测试路由
    url(r'^test/', views.Test.as_view())
# 导入权限类
from app01.permissions1 import RootPermission


# 测试视图类
class Test(APIView):
    # 局部认证
    permission_classes = [RootPermission]
    per = [RootPermission, ]

    def post(self, request):
        return Response('权限通过!')

* 3. 测试
携带token去访问Test
小米1 对应的token  42243e2c-564e-4110-a503-92f482cebf46
小米3 对应的token  847ed6a9-c8e5-4fab-9e7c-ed93d73c9a6d

image-20220421100458802

image-20220421100425953

* 4. 设置为全局权限认证
# settings.py 中设置全局配置认证类
REST_FRAMEWORK = {
    
    
    'DEFAULT_AUTHENTICATION_CLASSES': ['app01.authentication1.LoginAuthentication', ],
    'DEFAULT_PERMISSION_CLASSES': ['app01.permissions1.RootPermission'],
}
# 登入功能
class Login(APIView):
    # 登入不校验token, 不认证权限
    authentication_classes = []
    permission_classes = []

1.3 内置权限

* 1. 为内置用户表创建超级管理员账户
python3.6 manage.py createsuperuser
用户名: Python
密码:   zxc123456

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jEP4OrbW-1650612625754)(C:/Users/13600/AppData/Roaming/Typora/typora-user-images/image-20220421132629797.png)]

* 2. 测试路由
    # 内置权限测试
    url(r'^test2/', views.Test2.as_view())
* 3. 测试视图类
# 内置登入认证类
from rest_framework.authentication1 import SessionAuthentication
# 内置权限认证类
from rest_framework.permissions import IsAdminUser


# 内置权限测试
class Test2(APIView):
    authentication_classes = [SessionAuthentication, ]
    permission_classes = [IsAdminUser]
	# 请求方法
    def post(self, request):
        return Response('权限通过!')
* 4. 超级用户登录到admin后台管理, 在再访问test2

image-20220421133951562

权限判断是用户表的is_staff字段的值

image-20220421134153848

将值修改为false在测试
1 - true
0 - false

image-20220421134409036

2022-04-21_00263

2. 频率

频率: 用户一定时间内访问的次数. 
限流: Throttling, 可以对接口的频次进行限制, 以此减轻服务器的压力.

2.1 内置的频率限制

# 导入
from rest_framework.throttling import AnonRateThrottle, UserRateThrottle, ScopedrATEtHROTTLE
1. AnonRateThrottle 限制所有的未认证用户, 使用的ip区分用户.
使用DEFAULT_THROTTLE_RATES['anon': '次数/m']  设置频次
2. UserRateThrottle 限制认证用户, 使用User id来区分.
使用DEFAULT_THROTTLE_RATES['user': '次数/m']  设置频次
3. ScopedrATEtHROTTLE  限制用户对每个视图的访问频次, 使用ip或user id区分
次数/m 每分钟多少次, /后面只要是m开头即可, mzz, mxx, 都可以, 源码中截取开头第一个字符...
second秒  minute分钟 hour小时 day天

2.2 未登入限制

1. 全局配置
'DEFAULT_THROTTLE_CLASSES': ['rest_framework.throttling.AnonRateThrottle',] 'DEFAULT_THROTTLE_RATES': {
    
    'anon': '3/m', },
DEFAULT_THROTTLE_CLASSES属性对应使用的限制模块,
每配置一个频率限制就需要有一个对应DEFAULT_THROTTLE_RATES, 在该属性中配置限制模式.
* 限制未登入用户的每分钟可以访问3. 将认证和权限关闭.
# 全局配置认证类
REST_FRAMEWORK = {
    
    
    # 使用AnonRateThrottle模块
    'DEFAULT_THROTTLE_CLASSES': ['rest_framework.throttling.AnonRateThrottle', ],
    # 现在所有频率模块的频次      anon模块的频次 每分钟3次
    'DEFAULT_THROTTLE_RATES': {
    
    'anon': '3/m', },
}
* 1. 测试路由
    # 未登入频次限制
    url(r'^test3/', views.Test3.as_view()),
* 2. 测试视图
# 频次测试
class Test3(APIView):

    def get(self, request):
        return Response('test3!')
* 3. 测试 
	 get请求 127.0.0.1:8000/test3/

GIF 2022-4-21 14-49-32

2. 局部配置
为需要的视图类设置 throttle_classes属性, 
throttle_classes = [限制类]
# 全局配置认证类中配置频次
REST_FRAMEWORK = {
    
    
    # 现在所有频率模块的频次      anon模块的频次 每分钟3次
    'DEFAULT_THROTTLE_RATES': {
    
    'anon': '3/m', },
}
# 频次测试
from rest_framework.throttling import AnonRateThrottle


class Test3(APIView):
    # 局部设置当前类使用的限流模块
    throttle_classes = [AnonRateThrottle, ]

    def get(self, request):
        return Response('test3!')
局部配置测试

GIF 2022-4-21 14-56-06

2.3 登入用户限制

限制登入的用户每分钟可以访问5. 将登入验证打开.
过程简诉: 登入认证之后, 将用户的数据封装到requesr.user中, 使用UserRateThrottle, 
需要用户数据有有一个is_authenticated字段, 作为认证的依据.
为用户表添加is_authenticated字段
# 用户表
class User(models.Model):
    # 用户名称
    username = models.CharField(max_length=32)
    # 用户密码
    password = models.CharField(max_length=32)
    # 身份标识
    identity = models.IntegerField(choices=((1, '小米1'), (2, '小米2'), (3, '小米3')))
    # 认证标识, 默认为True
    is_authenticated = models.BooleanField(default=True)
python manage.py makemigrations
python manage.py migrate

image-20220421163251551

1. 全局配置
可以同时配置AnonRateThrottle  UserRateThrottle.
# 全局配置认证类
REST_FRAMEWORK = {
    
    
    # 开启token认证
    'DEFAULT_AUTHENTICATION_CLASSES': ['app01.authentication1.LoginAuthentication', ],
    # 配置频次
    'DEFAULT_THROTTLE_CLASSES': [
        # AnonRateThrottle模块限制未登入的访问频次
        'rest_framework.throttling.AnonRateThrottle',
        # UserRateThrottle模块现在登入的访问频次
        'rest_framework.throttling.UserRateThrottle', 

    ],
    # 现在所有频率模块的频次   (未登入频次 每分钟3次) (登入频次 每分钟5次)
    'DEFAULT_THROTTLE_RATES': {
    
    'anon': '3/m', 'user': '5/m'},
}
* 1. 测试路由
    # 登入用户频次限制
    url(r'^test4/', views.Test4.as_view()),
* 2. 测试视图类
# 登入用户频次测试
class Test4(APIView):
    # 开启频次限制
    def post(self, request):
        return Response('test4!')

* 3. 测试, 携带token
post: 127.0.0.1:8000/test4/
提交数据:
{
    
    
	"token": "42243e2c-564e-4110-a503-92f482cebf46"
}

GIF 2022-4-21 16-18-26

2.局部配置
将全局的配置注释掉, 在测试视图中设置 throttle_classess属性.
# 全局配置认证类
REST_FRAMEWORK = {
    
    
    # 认证token
    'DEFAULT_AUTHENTICATION_CLASSES': ['app01.authentication1.LoginAuthentication', ],
    # 现在所有频率模块的频次      未登入频次 每分钟3次 登入频次每分钟5次
    'DEFAULT_THROTTLE_RATES': {
    
    'anon' 'user': '5/m'},
}
from rest_framework.throttling import UserRateThrottle


class Test4(APIView):
    throttle_classes = [UserRateThrottle, ]
    # 开启频次限制
    def post(self, request):
        return Response('test4!')

3. 使用内置权限
使用SessionAuthentication, 作为登入认证检, 请求换为get.
# 登入用户频次测试
# auth模块登入认证
from rest_framework.authentication import SessionAuthentication
# 登入访问限制模块
from rest_framework.throttling import UserRateThrottle


class Test4(APIView):
    # 使用auth模块的认证
    authentication_classes = [SessionAuthentication]
    # 登入账户频率限制
    throttle_classes = [UserRateThrottle, ]
    # 开启频次限制
    def get(self, request):
        return Response('test4!')

image-20220421164538815

3. 过滤

过滤Filtering, 在继承值GenericAPIview的视图类, 在获取所有数据时, 可以设置根据字段进行过滤数据.
需要视图类有queryset属性的值, 拿出做处理. APIview不满足这个条件.
需要安装dango-filter模块
pip install django-filter

3.1 准备环境

* 1. 为book表添加数据

2022-04-21_00272

基于ListAPIView写一个查询所有数据的接口
* 2. 过滤测试路由
    # 过滤测试
    url(r'^books/', views.BookListAPIView.as_view())
* 3. 过滤测试视图类
from rest_framework.generics import ListAPIView


class BookListAPIView(ListAPIView):
    # 设置queryset 属性
    queryset = models.Book.objects.all()
    # 使用的模型序列化器
    serializer_class = BookModelSerializers
* 4. 查询测试

image-20220421204115249

3.2 全局配置

* 1. settings.py配置文件的app应用列表中注册 django_filter
INSTALLED_APPS = [
	...
    'rest_framework',
]
* 2. 全局配置
REST_FRAMEWORK = {
    
     
    ...
    'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend']
}
* 3. 在视图类中添加filter_fields属性, 指定可以过滤的字段
from rest_framework.generics import ListAPIView


class BookListAPIView(ListAPIView):
    # 设置queryset 属性
    queryset = models.Book.objects.all()
    # 使用的模型序列化器
    serializer_class = BookModelSerializers
    # 指定需要过滤的字段
    filter_fields = ['title', 'publish']
* 4. 过滤查询测试, 单条件测试

image-20220421204230349

* 5. 过滤查询测试, 多个条件测试, 关系为and.

image-20220421204047065

3.3 局部配置

# 导入过滤类
from django_filters.rest_framework import DjangoFilterBackend
# 视图类中设置filter_backends属性值
filter_backends = [DjangoFilterBackend]
* 1. 局部配置
from rest_framework.generics import ListAPIView

from django_filters.rest_framework import DjangoFilterBackend


class BookListAPIView(ListAPIView):
    # 设置queryset 属性
    queryset = models.Book.objects.all()
    # 使用的模型序列化器
    serializer_class = BookModelSerializers
    filter_backends = [DjangoFilterBackend]
    # 指定需要过滤的字段
    filter_fields = ['title', 'publish']
* 2. 过滤测试

image-20220421210545384

4. 排序

在视图类中设置filter_backends, rest_framework.OrderingFilter过滤器, rest_framework会在请求的查询
字符串参数中包含了ordering参数, 如果包含ordering参数, 则按照ordering参数指明的字段对数据集合进行排序.
在视图类中设置ordering_fields属性设置可选字段, 在前端传递ordering参数.

4.2 局部配置

# 导入排序模块
from rest_framework.filters import OrderingFilter
# 视图类的 filter_backends属性 设置排序模块
filter_backends = [OrderingFilter]
# 视图类的 ordering_fields 属性设置可以排序的字段
ordering_fields = ('id',)
?ordering=id 默认排序
?ordering=-id 倒序

4.1 全局配置

# 全局配置认证类
REST_FRAMEWORK = {
    
    
    'DEFAULT_FILTER_BACKENDS': ['rest_framework.filters.OrderingFilter',],
}
from rest_framework.generics import ListAPIView

class BookListAPIView(ListAPIView):
    # 设置queryset 属性
    queryset = models.Book.objects.all()
    # 使用的模型序列化器
    serializer_class = BookModelSerializers
	# 定义可以排序的字段
    ordering_fields = ('id',)
GET请求: 127.0.0.1:8000/books/?ordering=-id

image-20220421221305184

4.2 局部配置

from rest_framework.generics import ListAPIView
from rest_framework.filters import OrderingFilter


class BookListAPIView(ListAPIView):
    # 设置queryset 属性
    queryset = models.Book.objects.all()
    # 使用的模型序列化器
    serializer_class = BookModelSerializers

    filter_backends = [OrderingFilter]
    ordering_fields = ('id',)

GET请求: 127.0.0.1:8000/books/?ordering=-id

image-20220421220342995

4.3 过滤排序

1. 全局配置
# 全局配置认证类
REST_FRAMEWORK = {
    
    
    'DEFAULT_FILTER_BACKENDS': [
        # 过滤排序
        'django_filters.rest_framework.DjangoFilterBackend',
        # 过滤排序
        'rest_framework.filters.OrderingFilter', ],
}
from rest_framework.generics import ListAPIView


class BookListAPIView(ListAPIView):
    # 设置queryset 属性
    queryset = models.Book.objects.all()
    # 使用的模型序列化器
    serializer_class = BookModelSerializers
    # 过滤的字段
    filter_fields = ['publish']
    # 排序的字段
    ordering_fields = ('id',)

GET请求: 127.0.0.1:8000/books/?publish=aa出版社&ordering=-id

image-20220421221801469

4.2 局部使用

* 注意点, filter_backends设置会覆盖全局设置! 如果需要配合使用就在局部设置中定义过滤排序模块.
from rest_framework.generics import ListAPIView
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import OrderingFilter


class BookListAPIView(ListAPIView):
    # 设置queryset 属性
    queryset = models.Book.objects.all()
    # 使用的模型序列化器
    serializer_class = BookModelSerializers
    # 过滤排序
    filter_backends = [DjangoFilterBackend, OrderingFilter]
    # 过滤的字段
    filter_fields = ['publish']
    # 排序的字段
    ordering_fields = ('id',)
GET请求: 127.0.0.1:8000/books/?publish=aa出版社&ordering=-id

image-20220421223026350

5. 异常处理

5.1 源码解析

APIView的内置异常模块

2022-04-21_00282

异常处理主要是组成返回给前端的响应信息

2022-04-21_00283

返回信息的封装追溯

image-20220421232412514

image-20220421232438959

image-20220421232454233

image-20220421232521528

2022-04-21_00289

只针对三大认证做了返回信息的处理, 其他的直接返回None.

5.2 自定义异常响应

只能全局配置, 自定义的异常响应, 值就是一个字符串, 不能是列表['自定义的异常响应']
REST_FRAMEWORK = {
    
    
'EXCEPTION_HANDLER': '自定义的异常响应', 
}
* 1. 自定义异常响应模块
# 导入异常处理程序
from rest_framework.views import exception_handler
# 导入状态码模块
from rest_framework import status


# 自定义异常响应
def exception_response(exc, context):
    response = exception_handler(exc, context)
    """
    response 的值有两种情况
    1. 三大认证异常的返回响应格式
    2. 其他的异常没有处理 返回None
    """
    # 判断response 的值是否为None
    if not response:
        # 按异不同的异常 自定义异常响应信息

        if isinstance(exc, ...):
            return Response(data={
    
    'code': 401, 'msg': str(exc)}, status=status.HTTP_401_UNAUTHORIZED)
        if isinstance(exc, Exception):
            return Response(data={
    
    'code': 402, 'msg': str(exc)}, status=status.HTTP_402_PAYMENT_REQUIRED)

    # 重新封装三大认证的返回值, 从response.data 中取出错误的信息 detail
    return Response(data={
    
    'code': 400, 'msg': response.data.get('detail')}, status=status.HTTP_400_BAD_REQUEST)
* 2. 全局配置
# 全局配置认证类
REST_FRAMEWORK = {
    
    
    # 认证
    'DEFAULT_AUTHENTICATION_CLASSES': ['app01.authentication1.LoginAuthentication', ],
    # 权限
    'DEFAULT_PERMISSION_CLASSES': ['app01.permissions1.RootPermission'],
    # 自定义异常响应
    'EXCEPTION_HANDLER': 'app01.response.exception_response',}
* 3. 测试路由
    # 自动生成 异常响应测试路由
    url(r'^books2/', views.BookListAPIView2.as_view()),
* 4. 测试视图类
from django.conf.urls import url
from django.contrib import admin

# 导入生成路由模块
from rest_framework import routers

# 导入视图层
from app01 import views

urlpatterns = [
	...
]

# 生成简单路由对象
router_obj = routers.SimpleRouter()

# 生成books api接口
router_obj.register('api/books/v1', views.BookListAPIView2)

# 将路由添加到路由列表中
urlpatterns += router_obj.urls

* 5. 测试视图类
from rest_framework.decorators import action


class BookListAPIView2(ModelViewSet):
    # 设置queryset 属性
    queryset = models.Book.objects.all()
    # 使用的模型序列化器
    serializer_class = BookModelSerializers

    @action(methods=['get',], detail=False)
    def get_two_obj(self, request):
        1/0
        return Response({
    
    '两条数据'})

* 6. 自定义异常响应
# 自定义异常响应
from rest_framework.views import exception_handler
from rest_framework import status
from rest_framework.response import Response


def exception_response(exc, context):
    print(exc, context)
    response = exception_handler(exc, context)

    """
    response 的值有两种情况
    1. 三大认证异常的返回响应格式
    2. 其他的异常没有处理 返回None
    """
    # 判断response 的值是否为None
    if not response:
        # 按异不同的异常 自定义异常响应信息

        if isinstance(exc, ZeroDivisionError):
            return Response(data={
    
    'code': 401, 'msg': str(exc)}, status=status.HTTP_401_UNAUTHORIZED)
        if isinstance(exc, Exception):
            return Response(data={
    
    'code': 402, 'msg': str(exc)}, status=status.HTTP_402_PAYMENT_REQUIRED)

    # 重新封装三大认证的返回值, 从response.data 中取出错误的信息 detail
    return Response(data={
    
    'code': 400, 'msg': response.data.get('detail')}, status=status.HTTP_400_BAD_REQUEST)
* 7. 登入认证测试
	 get请求不带token访问: 127.0.0.1:8000/api/books/v1/

image-20220422015737368

* 8. 权限测试, 带权限不能通过的...
     get请求带token访问: 127.0.0.1:8000/api/books/v1/
小米1 对应的token  42243e2c-564e-4110-a503-92f482cebf46
小米3 对应的token  847ed6a9-c8e5-4fab-9e7c-ed93d73c9a6d

image-20220422020005000

* 9. 自定义认证器中编写代码出现异常, 手动添加异常.

image-20220422015052225

get请求带token访问: 127.0.0.1:8000/api/books/v1/get_two_obj/

image-20220422015147152

get请求带满足权限的token访问: 127.0.0.1:8000/api/books/v1/get_two_obj/

image-20220422015327324

image-20220422015348741

* 10. 请求中编写代码出现异常
      get请求带满足权限的token访问: 127.0.0.1:8000/api/books/v1/get_two_obj/

image-20220422020444637

6. 封装Response

继承Response类, 重新定义返回数据的格式.
* 1. 响应类
from rest_framework import status
from rest_framework.response import Response
from rest_framework.status import *


# 正常响应
class NormalResponse(Response):

    def __init__(self, code=200, msg='访问成功', data=None, status=HTTP_200_OK, **kwargs):
        """
        :param code: 状态码
        :param msg: 返回信息
        :param data: 获取的数据
        :param status: 状态码
        :param kwargs: 其他参数
        """
        # 生成包含code 与 msg 的字段
        dic = {
    
    'code': code, 'msg': msg}
        # 判断data是否有值
        if data:
            # 将获取的数据data添加到字典
            dic.update(data=data)
        # 将其他参数添加到字典
        dic.update(kwargs)

        # 调用父类的方法生成对象
        super().__init__(data=dic, status=status)
* 2. 测试路由
    # 响应测试
    url(r'^test5/', views.TestAPIView.as_view())
* 3. 测试路由
from rest_framework.views import APIView
# 自定义响应对象
from app01.response import NormalResponse


class TestAPIView(APIView):
    def get(self, request):
        return NormalResponse(data={
    
    'id': 1, 'title': '小说1'})
get请求: 127.0.0.1:8000/test5/

image-20220422150200215

        return NormalResponse(data={
    
    'id': 1, 'title': '小说1'}, token='xadasdadasd')

image-20220422152140049

        return NormalResponse(101, '失败', status=status.HTTP_101_SWITCHING_PROTOCOLS)

image-20220422152026667

猜你喜欢

转载自blog.csdn.net/qq_46137324/article/details/124347160