IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> 3.DRF 自动生成路由 -> 正文阅读

[Python知识库]3.DRF 自动生成路由

0.准备环境

* 1. 新建项目 DRF_03

image-20220418230046968

# 修改模型成的路径问题
TEMPLATES = [
    ...
        'DIRS': [BASE_DIR, 'templates']
# 将rest_framework 注册到app列表
INSTALLED_APPS = [
    ...
	    'rest_framework',
* 2. 创建模型表
from django.db import models


# Create your models here.
# 书籍表
class Book(models.Model):
    # 主键
    id = models.AutoField(primary_key=True)
    # 书名
    title = models.CharField(max_length=32, verbose_name='书名')
    # 价格
    price = models.DecimalField(max_digits=5, decimal_places=2, verbose_name='价格')
    # 作者
    author = models.CharField(max_length=32, verbose_name='作者')
# 创建表
生成操作记录 python manage.py makemigratons
生成数据表 python manage.py magrate
* 3. 定义序列化器
# 定义模型序列化器
# 1. 导入模型序列化类
from rest_framework import serializers
# 2. 导入表模型
from app01.models import Book


# 3. 定义书籍模型序列化器, 继承模型序列化类
class BookSerializer(serializers.ModelSerializer):
    # 3.1 定义Meta类
    class Meta:
        # .1 指定模型表
        model = Book
        # .2 定义需要转换的字段
        fields = "__all__"
* 4. 定义路由
    # 2. APIView Book
    url(r'^api/books/v1/', views.BookAPIView1.as_view()),
    url(r'^api/books/v1/(?P<pk>\d+)/', views.BookAPIView2.as_view())
* 5. 使用视图子类写接口
from django.shortcuts import render

# Create your views here.

# 1. 导入请求视图子类
from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView

# 2. 导入书籍表模型
from app01.models import Book

# 3. 导入序列化器
from app01.serializer import BookSerializer


# 3. 定义BookAPIView1
class BookAPIView1(ListCreateAPIView):
    # 3.1 定义 queryset 设置表模型
    queryset = Book.objects
    # 3.2 定义 serializer_class 设置使用的序列化器
    serializer_class = BookSerializer


# 4. 定义BookAPIView2
class BookAPIView2(RetrieveUpdateDestroyAPIView):
    # 4.1 定义 queryset 设置表模型
    queryset = Book.objects
    # 4.2 定义 serializer_class 设置使用的序列化器
    serializer_class = BookSerializer
* 6. 第二组路由
	# 3. ViewSet Book
    url(r'^api/books/v2/', views.BookModelViewSet1.as_view(actions={'get': 'list', 'post': 'create'})),
    url(r'^api/books/v2/(?P<pk>\d+)/',
        views.BookModelViewSet1.as_view(actions={'get': 'retrieve', 'put': 'update', "delete": "destroy"}))
将第二个路由写进了第一个路由里面...

image-20220419102137354

* 7. 使用视图集编写接口
# 5.导入视图集
from rest_framework.viewsets import ModelViewSet


class BookModelViewSet1(ModelViewSet):
    # 定义 queryset 设置表模型
    queryset = Book.objects
    # 定义 serializer_class 设置使用的序列化器
    serializer_class = BookSerializer

1. 路由

1.1 CBV传统路由

# 方式1
url(r'^api/books/v1/', views.BookAPIView1.as_view()),
请求来的时候, 先执行as_view方法, 返回一个view函数内存地址, view函数中通过dispacth中通过判定当前请求, 
执行了对应的请求方法, 对应的请求方法再去调用视图子类的方法.

1.2 继承ViewSetMixin

eg: 
get不带主键 --> get方法 --> list方法
get带主键   --> get方法 --> retrieve方法
继承了ViewSetMixin
get不带主键 --> get方法(list)
get带主键   --> get方法(retrieve方)
# 方式2 继承了ViewSetMixin
url(r'^api/books/v2/', views.BookModelViewSet1.as_view(actions={'get': 'list'}))
请求来的时候, 先执行as_view方法, 返回被重写的view函数内存地址, view函数中遍历actions字段,
为对象添绑定方法, 最后通过dispacth执行对应的请求方法时, 执行的是视图子类的方法.

1.3 自动生成路由

# 方式3 继承了ModelViewSet 使用 routers模块自动生成路由
from rest_framework import routers
routers模块有两个类
1. SimpleRouter  自动生成两条路由
2. DefaultRouter 自动生成六条路由
SimpleRouter  DefaultRouter 的使用方式是一模一样的

对象.register('前缀', '继承至ModelViewSet的视图类', 匿名函数等其他的参数...)
前缀会自动加上^/ , 视图类会自定加上.as_view()
# 继承了ModelViewSet 使用 routers模块自动生成路由

# 1. 导入routers模块
from rest_framework import routers
# 2. 实例化得到对象
router = routers.SimpleRouter()
# 3. 注册 成路由, 生成的路由被存放在urls属性中
router.register('api/books/v3', views.BookModelViewSet2)
print(router.urls)
"""
[<RegexURLPattern book-list ^api/books/v3/$>, 
<RegexURLPattern book-detail ^api/books/v3/(?P<pk>[^/.]+)/$>]
"""
# 4. 将自动生成的路由列表添加到路由列表中
urlpatterns += router.urls
两个路由列表相加 = [列表]
# 对应的视图
class BookModelViewSet2(ModelViewSet):
    # 定义 queryset 设置表模型
    queryset = Book.objects
    # 定义 serializer_class 设置使用的序列化器
    serializer_class = BookSerializer
SimpleRouter
# 127.0.0.1:8000/xxx/
[<RegexURLPattern book-list ^api/books/v3/$>,
#  127.0.0.1:8000/xxx/num/
<RegexURLPattern book-detail ^api/books/v3/(?P<pk>[^/.]+)/$>]

DefaultRouter
# 127.0.0.1:8000/xxx/
[<RegexURLPattern book-list ^api/books/v3/$>,
#  127.0.0.1:8000/xxx.后缀/  随意带后缀
<RegexURLPattern book-list ^api/books/v3\.(?P<format>[a-z0-9]+)/?$>,

#  127.0.0.1:8000/xxx/num/
<RegexURLPattern book-detail ^api/books/v3/(?P<pk>[^/.]+)/$>, 
#  127.0.0.1:8000/xxx/num.后缀/ 随意带后缀
<RegexURLPattern book-detail ^api/books/v3/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$>,

# 127.0.0.1:8000
<RegexURLPattern api-root ^$>,
# 127.0.0.1:8000/.后缀/  随意带后缀
<RegexURLPattern api-root ^\.(?P<format>[a-z0-9]+)/?$>]

DefaultRouter 添加了一个主页路由, 然后在为每个路由设置一个可带.后缀的路由.

1.4 action装饰器

使用routers模块自动生成路由, 默认只能生成增, , , 查全部, 查一条的功能, 
在视图类中定义其他的方法后, 自动生成改方法的路由则需要action装饰器. 
# 导入action装饰器 
from rest_framework.decorators import action

action装饰器有两个参数(必须填)
1. methods 为装饰的方法设置请求方式, 值为一个列表.
2. detail 生成的路由是否包含有名分组获取pk值, 

@action(methods=['请求方法', ], detail=False)
def xxx(self, request)...

@action(methods=['请求方法', ], detail=True)
def xxx(self, request, pk)...

2022-04-19_00214

定义一个方法, 获取两条数据并返回.(提前创建几条数据)
self.get_queryset()[:2]
# 导入action装饰器
from rest_framework.decorators import action
# 导入Response
from rest_framework.response import Response


class BookModelViewSet2(ModelViewSet):
    # 定义 queryset 设置表模型
    queryset = Book.objects
    # 定义 serializer_class 设置使用的序列化器
    serializer_class = BookSerializer

    # 自定义方法
    @action(methods=['get'])
    def get_data(self, request):
        # self.get_queryset() 是一个queryset列表 可以切分, 切出来的还是一个列表
        book_obj = self.get_queryset()[:2]
        # 序列化模型对象
        book_dic = self.serializer_class(book_obj, many=True)  # 只要通过索引切分后的值, 就是一个列表, 是列表, many就要设置为True
        # 返回数据
        return Response(book_dic.data)

2022-04-19_00211

^api/books/v3/get_data/$ [name='book-get-data']
访问地址: 127.0.0.1:8000/api/books/v3/get_data/

image-20220419131606478

    # detail=True 路由中设置有名分组,获取值, 定义的方法中也需要接受值
    @action(methods=['get'], detail=True)
    def get_data(self, request, pk):
        print(pk)  # 显示主键
        ...
^api/books/v3/(?P<pk>[^/.]+)/get_data/$ [name='book-get-data']
请求地址: 127.0.0.1:8000/api/books/v3/主键/get_data/

2022-04-19_00213

2. 认证

认证的实现: 写一个类, 继承BseAuthentication, 
在类中重写authenticate方法, 将该方法中写认证的逻辑.可以局部使用, 也可以全局使用.

2.1 认证源码解析

* 1. APIView类的dispatch方法中 self.initial(request, *args, **kwargs)
initial 有认证, 频率, 权限三大认证模块 , request是Request模块生成的request

2022-04-19_00215

* 2. 执行认证的方法将request对象传入

2022-04-19_00216

* 3. 方法中request.user, 去查找Request中查找对象的user静态方法

2022-04-19_00217

* 4. Request的user方法中, request._user中是否有值, 
     第一次知道值肯定不存在的, 执行._authentications方法
     这里的self是 request, 这个方法是上面request.user调用的

20220419163436

* 5. 核心代码 self是Request的request对象
	authenticators是一堆需要认证的类 产生的对象 组成的一个列表.
     遍历从列表中拿出对象, 进行认证.

image-20220419171517103

self是Request的request对象

authenticator.authenticate(self) 认证器(对象)调用认认证方法
authenticator对象是自己写的, authenticate方法也是需要自己写的

执行之后
认证成功了需要返回一个元组, (登入的用户, 认证的信息)
之后将这个数组解压赋值给self.user和self.auth,  self是Request封装的request.
认证失败是需要抛异常, APIEcception
一般写的时候是, AuthenticatonFailed AuthenticatonFailed继承了APIEcception, 
也符合APIEcception的异常捕获的条件. 以后写其他的认证, 抛出的异常也继承APIEcception, 在它的基础在细分.

2022-04-19_00225

authenticator.authenticate(self) 
authenticator是对象, 对象点方法将自己最为第一个参数进行传递, 这里的self是request
authenticator.authenticate(authenticator, request) 这里传递了两个参数!
if user_auth_tuple is not None, 
不为空, 认证类认证成功会返回的连个数据值分别被request的两个属性接受, 之后直接结束这个函数.
为空, 执行self.not_authenticated, 将request.user信息设置为游客
 authenticators的追溯

image-20220419165009296

authenticators 要是Request实例化传入的值, 要么是()

2022-04-19_00221

这里的self是视图类的对象
执行get_authenticators得到的是一个列表生成器, 
self.authentication_classes 需要自己在视图类中定义, 
class xx(xxAPIView):
     authentication_classes = ['类', ]
    ...
 自己不定义就跑到配置文件去找.
 
 遍历存放的类, 加括号调用, 得到存放对象的列表.

2022-04-19_00222

这里的self是视图类的对象
api.settings配置文件

2022-04-19_00223

image-20220420103143140

2.2 视图类中做检验

在用户登入一次之后将token返回非客户端, 下次访问信息, 携带token进行校验, 校验通过能拿到用户的信息.
* 1. 准备两种表并写入数据
     UserToken表一对一用户表, 通过token校验能马上拿到当前的用户.
# 创建用户表
class User(models.Model):
    # 主键
    id = models.AutoField(primary_key=True, verbose_name='主键')
    # 用户名
    username = models.CharField(max_length=32, verbose_name='用户名称')
    # 用户密码
    password = models.CharField(max_length=32, verbose_name='用户名密码')
    # 等级
    grade = models.IntegerField(choices=((1, '黄金会员'), (2, '白银会员'), (3, '褐铜用户')), verbose_name='等级')


# 创建登入验证表, 记录痛token
class UserToken(models.Model):
    # 主键
    id = models.AutoField(primary_key=True, verbose_name='主键')
    # token值
    token = models.CharField(max_length=64, verbose_name='token')
    # 一对一关联用户表, 设置级联删除
    user = models.OneToOneField(to=User, on_delete=models.CASCADE, verbose_name='外键字段,关联用户的id')

* 2. 生成表记录并迁移数据库
python manage.py makemigrations
python manage.py migrate
* 3. 为用户表添加上三条数据

image-20220419213439612

* 4. 路由
    # 登入校验测试
    url(r'^login/', views.LoginAPIView.as_view()),
* 5. 登入视图类, 每次重新登入成功都会触发uuid4(), 随之更新token的值
# 导入继承视图
from rest_framework.views import APIView
# 导入模型层
from app01 import models
# 导入 uuid 32位随机字符串模块 uuid4不需要参数 1 3 5要参数
from uuid import uuid4
# 导入响应模块
from rest_framework.response import Response


# 登入校验
class LoginAPIView(APIView):
    # 定义请求方法
    def post(self, request):
        # 从request中获取用户名称和用户密码
        print(request.data)  # {'username': 'kid', 'password': '111'}
        username = request.data.get('username')
        password = request.data.get('password')

        # 去用户表中校验
        user_obj = models.User.objects.filter(username=username, password=password).first()
        # 判断校验的结果, 校验不成功值属于False类型
        if user_obj:
            # 校验成功生成一个随机字符串
            token = uuid4()
            print(token)
            # 将token存入数据库 update_or_create() 存在则更新, 不存在则创建
            models.UserToken.objects.update_or_create(defaults={'token': token}, user=user_obj)
            return Response({'code': 200, 'msg': '登入成功!', 'token': token})
        # 校验不成功直接返回错误提示信息
        else:
            return Response({'code': 100, 'msg': '用户名称或密码错误!'})
objects.update_or_create(self, defaults=None, **kwargs)
defaults为更新的值 **kwargs 为查询的依据
1. 使用依据匹配到数据, 将defaults的值更加到该数据库.
2. 使用依据查没有匹配到数据, 将defaults的值,  **kwargs的值作为表的数据创建.
* 6. Postman中测试: 127.0.0.1:8000/login/ 
post请求携带json格式数据:
{
    "username": "kid",
    "password": "111"
}

image-20220419221729934

2.3 自定义认证组件

如果有多个认证类, 前面都不需要返回用户对象和信息, 在最后才返回即可.
一旦在前面直接返回了, 后面的认证类就不会在走了.
* 1. 在app01下创建一个auth.py文件, 在文件中写校验类.
校验类需要继承 基本身份验证类,源码↓
父类中规范子类必须实现某个功能, 不写就抛出异常.

image-20220419210819581

# 导入 基本身份验证 模块
from rest_framework.authentication import BaseAut	hentication	
	
# 导入异常模块
from rest_framework.exceptions import AuthenticationFailed

# 导入模型层
from app01 import models


# 定义校验类, 必须继承BaseAuthentication
class LoginCheck(BaseAuthentication):
    # 在校验类中写 authenticate方法
    def authenticate(self, request):
        """
        self 是当前类的对象, request 是Request重新封装的request
        写认证的逻辑,
        认证成功返回一个数组,(登入的用户对象, token)
        认证失败抛出 AuthenticationFailed异常
        """
        # 1. 去请求中取token 在去数据库中做校验
        print(request.data)
        token = request.GET.get('token')
        print(token)
        # token = request.query_params('token')
        # print(token)
        # 没有提供token直接抛出异常
        if not token:
            raise AuthenticationFailed('没有携带token值!')

        # 拿token值去数据库中校验
        token_obj = models.UserToken.objects.filter(token=token).first()
        # 判断检验是否合格
        if not token_obj:
            raise AuthenticationFailed('校验不合格!')

        # 校验成功返回用户对象 和 token
        return (token_obj.user, token)
token_obj = models.UserToken.objects.filter(token=token).first()
通过token做校验, 检验成果之后, token_obj.user就直接拿到当前token对应的用户数据对象.
* 2. 局部使用认证
	# 导入认证类
    from app01.auth import LoginCheck
    # 为需要校验的数图类设置authentication_classes属性
	authentication_classes = [LoginCheck]
# 导入action装饰器
from rest_framework.decorators import action
# 导入Response
from rest_framework.response import Response

# 导入认证类
from app01.auth import LoginCheck


class BookModelViewSet2(ModelViewSet):
    # 添加校验
    authentication_classes = [LoginCheck]
    # 定义 queryset 设置表模型
    queryset = Book.objects.all()
    # 定义 serializer_class 设置使用的序列化器
    serializer_class = BookSerializer

    # 自定义方法
    @action(methods=['get'], detail=True)
    def get_data(self, request, pk):
        print(f'主键:{pk}') 
        print(f'用户的模型对象:{request.user}')
        print(f'token值:{request.auth}')
        book_obj = self.get_queryset()[:2]
        # 序列化模型对象
        book_dic = self.serializer_class(book_obj, many=True) 
        # 返回数据
        return Response(book_dic.data)
* 3. 校验测试
第一次请求不携带token
127.0.0.1:8000/api/books/v3/

image-20220419224932220

第二次请求携带错误的token值
127.0.0.1:8000/api/books/v3/

image-20220419225040944

第三次请求携带正确的token
127.0.0.1:8000/api/books/v3/

image-20220419225303326

当检验成功之后, 返回两个值分别为request.user 和reqquest.auth设置了值.
在请求方法中可以使用这两个属性. 如果在请求方法中不需要使用则会两个属性, 那么定义认证中就不需要返回值了.
* APIView中访问request.user 是匿名用户.
* 认证类中没人返回参数 那么在请求中访问中request.user也是匿名用户.
127.0.0.1:8000/api/books/v3/1/get_data/?token=1e33392c-2f68-4c82-926a-dde4f5c5bac6

image-20220419230708199

* 5. 全局配置 在settings.py 
REST_FRAMEWORK ={
    'DEFAULT_AUTHENTICATION_CLASSES': ['app01.auth.LoginCheck',]
}
设置之后存在一个问题, 第一次登入也需要认证, 就陷入死局了.
为登入接口设置局部校验为空, 
authentication_classes = []
查找自己的类属性优先级最高,
注销局部BookModelViewSet2的局部校验
为LoginAPIView设置局部校验为空.
class BookModelViewSet2(ModelViewSet):
    # 添加校验
    # authentication_classes = [LoginCheck]
    ...

# 登入校验
class LoginAPIView(APIView):
    # 添加校验
    authentication_classes = []
    ...
登入测试, 每一次重新登入, token的值都被重新修改了

image-20220419235039637

image-20220419235132533

127.0.0.1:8000/api/books/v3/1/get_data/?token=1e33392c-2f68-4c82-926a-dde4f5c5bac6
只有经过校验request才会有自己在校验类中返回的信息.

image-20220419234741557

2.4 认证练习

1. 继承ModelViewSet, 实现所有接口, 单独写一个接口获取2条数据.
2. 路由自动生成, 获取两条数据的接口使用couter生成, 
3. 认证组件全局使用, 登入禁用, token信息存放在请求头中.
1. 准备环境
* 1. 新建项, 不要模板层, templates信息删除.

image-20220420105030240

* 2. 创建两张表
# books_msg/modes.py
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)


# token记录表
class Token(models.Model):
    # token值
    token_value = models.CharField(max_length=64)
    # 外键一对一关联用户表, 设置级联删除
    user = models.OneToOneField(to=User, on_delete=models.CASCADE)

    
# 书籍表
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-20220420113713800

为书籍表创建三条数据

image-20220420130958679

* 3. 将rest_framework 添加到app应用列表中
# settings.py
# Application definition

INSTALLED_APPS = [
    ...
    'rest_framework',
]
2. 登入功能
* 1. 登入路由
    # urls.py
    # 登入功能
    url(r'^login/', views.Login.as_view())
* 2. 登入视图类
# books_msg/views.py
# 导入APIview
from rest_framework.views import APIView

# 导入模型层
from books_msg import models

# 导入随机字符串模块
import uuid

# 导入响应模块
from rest_framework.response import Response

# 导入响应状态码
from rest_framework import status


# 登入
class Login(APIView):

    # 定义登入校验方法
    def post(self, request):
        # 获取提交的账户和密码去数据库中校验  **request.data 对字典格式数据解压赋值
        print(request.data)
        # 获取值
        username = request.data.get('username')
        password = request.data.get('password')
        
        # 值不能为空
        if not (username and password):
            return Response({'code': 101, 'msg': '用户或密码没有输入!'}, status=status.HTTP_101_SWITCHING_PROTOCOLS)

        # 去数据库中校验值
        user_obj = models.User.objects.filter(username=username, password=password).first()
        print(user_obj)
        # 判断用户对象是否有数据, 没有数据直接return
        if not user_obj:
            return Response({'code': 101, 'msg': '用户或密码错误!'}, status=status.HTTP_101_SWITCHING_PROTOCOLS)

        # 生成一个 uuid
        token = uuid.uuid4()

        # 将值存入到数据库中, update_or_create 有则跟新, 没有则创建
        models.Token.objects.update_or_create(defaults={'token_value': token}, user=user_obj)

        # 返回登入信息
        return Response({'code': 200, 'msg': '登入成功', 'token': token}, status=status.HTTP_200_OK)
* 3. Postman中登入测试
post请求  127.0.0.1:8000/login/  
json数据:
{
    "username": "kid",
    "password": "123"
}

image-20220420124543505

3. 编写接口
增删改查, 外加一个获取2条数据的请求.
* 1. 自动生成路由
from django.conf.urls import url
from django.contrib import admin
# 导入视图层
from books_msg import views
# 导入自动生成路由模块
from rest_framework import routers

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

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    # 登入功能
    url(r'^login/', views.Login.as_view())
]

# 生成booksAPI路由,  存放在 对象.urls
router.register('api/books/v1', views.BookModelSetView)
print(router.urls)
# 将生成的路由添加到路由列表中
urlpatterns += router.urls
* 2. 书籍表模型序列化器
# 导入模型序列化器
from rest_framework import serializers
# 导入模型层
from books_msg import models


# 定义用户表模型序列化器
class BookModelsSerializer(serializers.ModelSerializer):
    # 定义Meta类
    class Meta:
        model = models.Book
        fields = '__all__'

* 3. API视图类
	 继承了ModelSetView类必须设置queryset, serializer_class属性值
# 导入数图集
from rest_framework.viewsets import ModelViewSet

# 导入自己定义模型序列化器
from books_msg import ModelSerializer


class BookModelSetView(ModelViewSet):
    # 设置queryset属性, 值是表的所有数据对象
    queryset = models.Book.objects.all()
    # 设置serializer_class属性, 值是需要使用序列化器
    serializer_class = ModelSerializer.BookModelsSerializer
* 3. Postman中测试, 查询所有的数据 	127.0.0.1:8000/api/books/v1/

image-20220420131111552

* 4. 获取两条数据的接口
class BookModelSetView(ModelViewSet):
    # 设置queryset属性, 值是表的所有数据对象
    queryset = models.Book.objects.all()
    # 设置serializer_class属性, 值是需要使用序列化器
    serializer_class = ModelSerializer.BookModelsSerializer

    # 自动生成路由  127.0.0.1:8000/api/books/v1/get_two_data/
    @action(methods=['get'], detail=False)
    # 获取两条数据的接口
    def get_two_data(self, request):
        # 获取两条数据
        book_obj = self.queryset[:2]
        # 使用序列化器
        book_dic = self.serializer_class(instance=book_obj, many=True)
        # 返回数据
        return Response({'code': 200, 'msg': '获取成功', 'book_obj': book_dic.data}, status=status.HTTP_200_OK)

* 5. Postman中测试, 查询两条数据的接口	127.0.0.1:8000/api/books/v1/get_two_data/

image-20220420132329279

4.校验类
* 1. 校验类,   继承BseAuthentication, 类中必须有authenticate方法, 在该方法中写检验的逻辑.
# 导入 基本身份验证 模块
from rest_framework.authentication import BaseAuthentication

# 导入异常模块
from rest_framework.exceptions import AuthenticationFailed
# 导入模型层
from books_msg import models


# 登入认证
class LoginAuthentication(BaseAuthentication):
    # 该方法一定接收到两个参数, self是认证类的对象, request时Request重新封装的request对象
    def authenticate(self, request):
        # 要求是token值由请求头中携带
        # 获取请求头的的token, 在请求头中携带数据, 会自动为键加上HTTP_前缀
        print(request.META)
        token_value = request.META.get('HTTP_TOKEN')

        # 判断是否携带token 没有就直接抛出异常信息
        if not token_value:
            raise AuthenticationFailed('没有携带token值!')

        # 拿token值去数据库中比对
        token_obj = models.Token.objects.filter(token_value=token_value).first()

        # 判断校验结果, 没有匹配成功直接抛出异常
        if not token_obj:
            raise AuthenticationFailed('token值不正则')

        # 认证返回两个数据
        return token_obj.user, token_value

image-20220420140920230

请求头的携带自定义的数据, 键多了http_前缀, 还被转为大写.
放回 token_obj.user, token_value 分别被request.user  request.auth接收
在自定义获取两条数据的接口中可以查看request.user  request.auth的信息
    # 获取两条数据的接口
    def get_two_data(self, request):
        # 展示登入的用户和信息
        print(request.user, request.user.username)
        print(request.auth)
        ...
* 2. 全局配置登入校验, 登入不校验
# 在settings.py 中设置全局校验
# 全局登入校验
REST_FRAMEWORK = {  # 值一定要是列表或 元组 否则 TypeError: 'type' object is not iterable
    'DEFAULT_AUTHENTICATION_CLASSES': ['books_msg.authenticates.LoginAuthentication', ]
}
# 为登入功能设置局部不校验, 不设置就没法登入了.

# 登入
class Login(APIView):
    # 登入不校验
    authentication_classes = []
    ...
* 3. Postman中测试,post请求: 127.0.0.1:8000/api/books/v1/get_two_data/
     在请求头中添加token

image-20220420141004560

终端展示request.user  request.auth的值

image-20220420142001497

* 4. 重新登入, 刷新token值, 如果提示没有token, 就是局部禁用校验设置失败

image-20220420142226303

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2022-04-22 18:32:27  更:2022-04-22 18:35:19 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 18:04:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码