drf知识--07

2023-12-28 03:00:15

回顾之视图层

#?两个视图基类:

from rest_framework.views import??APIView
? ? ?? ?包装新的request、去除csrf认证、执行三大认证和处理全局异常
? ? ? ? -as_view
? ? ? ? -dispatch
? ? ? ? -parser_class
? ? ? ? -render_class

from rest_framework.generics import GenericAPIView
? ?继承自APIView
? ?类属性:queryset、serializer_class

# 方法:
get_queryset:子类可以重写
get_object :获取单条
get_serializer: 传参数,返回序列化类的对象
get_serializer_class :返回序列化类,不能传参数,再加括号用
? ? ?self.get_serializer(instance=qs,many=True)
? ? ?self.get_serializer_class()(instance=qs,many=True)
需要写跟 请求方式 同名的方法:get ?get ?post delete put 分到了两个类中
# views.py
from rest_framework.generics import GenericAPIView
from .models import Publish
from .serializer import PublishSerializer
 
class BookView(GenericAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    def get(self, request):
        object_list = self.get_queryset()  # 获取所有要序列化的数据
        ser = self.get_serializer(instance=object_list, many=True)  # 获取序列化类
        return Response(ser.data)
 
    def post(self, request):
        ser = self.get_serializer(data=request.data)
        if ser.is_valid():
            ser.save()
            return Response(ser.data)
        else:
            return Response(ser.errors)
 
class BookDetailView(GenericAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    def put(self, request, *args, **kwargs):
        obj = self.get_object()  # 获取单挑---》内部就是按pk从request中取,取出pk对应的值,查询的
        ser = self.get_serializer(instance=obj, data=request.data)
        if ser.is_valid():
            ser.save()
            return Response(ser.data)
        else:
            return Response(ser.errors)
 
    def get(self, request, *args, **kwargs):
        obj = self.get_object()
        ser = self.get_serializer(instance=obj)
        return Response(ser.data)
 
    def delete(self, request, *args, **kwargs):
        self.get_object().delete()
        return Response('')

#?5个视图扩展类:

? ? CreateModelMixin:create 就是原来继承GenericAPIView后post中写的代码
? ? ListModelMixin:list 就是原来继承GenericAPIView后get中写的代码
? ? DestroyModelMixin:destroy 就是原来继承GenericAPIView后delete中写的代码
? ? RetrieveModelMixin:retrieve 就是原来继承GenericAPIView后get中写的代码
? ? UpdateModelMixin:update 就是原来继承GenericAPIView后put中写的代码? ??
? ? 以后可以通过5个视图扩展类+GenericAPIView写接口--》还是要写 get ?get ?post delete put这些方法,但是具体内容可以直接使用父类的方法
? ? 但是如果通过5个视图扩展类+GenericViewSet写接口---》路由写法变了--》映射关系,自动生成---》get:list-->所以以后再视图类中不需要写跟请求方式同名的方法了---》一个视图类中就能完成5个接口

# 9个视图子类 --视图类:

????都会继承GenericAPIView+5个视图扩展类+跟请求方式同名的方法
? ? ????????UpdateAPIView
????????? ? RetrieveUpdateDestroyAPIView
? ????????? RetrieveUpdateAPIView
? ????????? RetrieveDestroyAPIView
? ????????? RetrieveAPIView
? ????????? ListCreateAPIView
? ????????? ListAPIView
????????? ? DestroyAPIView
????????? ? CreateAPIView
? ? 以后视图类,继承自上面9个之一,只需要写两个类属性,就会直接有接口

回顾之视图集

ViewSetMixin:只要继承了它,路由写法变了:映射 ?自动生成? 这个类必须视图类前面
ViewSet:ViewSetMixin+APIView 以后想路由自动生成,之前继承APIView的现在继承它
GenericViewSet:ViewSetMixin+GenericAPIView 以后想路由自动生成
ModelViewSet:快速实现5个接口,继承了ViewSetMixin+GenericAPIView+5个视图扩展类
ReadOnlyModelViewSet:快速实现2个接口

????????????????继承了ViewSetMixin+GenericAPIView+2个视图扩展类

# 以后视图类继承谁的问题?
?? ?-只想在视图类中写login接口
? ? ?? ?APIView---》post
? ? ? ? GenericViewSet---》login--》装饰器

回顾之路由

# 继承ViewSetMixin的视图类,路由写法变了:
? ? ?? ?映射的方式\自动生成的方式(这个用的多)
# 自动生成的使用步骤:
1、导入一个类:
? ? ? ? ?? ?from rest_framework.routers import SimpleRouter, DefaultRouter
2、类实例化得到对象
? ? ? ? ? ? router = SimpleRouter() ?# 生成的路径少
? ? ? ? ? ? router = DefaultRouter() # 多一个 / 路径
? ? ? ? ? ? ????????api/v1/--->显示了所有能访问的路由
? ? ? ? ? ????????? api/v1/books/
? ? ? ? ? ????????? api/v1/users/
3、注册视图类:有几个就注册几次
? ? ? ? ?? ?router.register('books', views.BookView, 'books')
? ? ? ? ? ? router.register('users', views.UserView, 'users')
4、在总路由中加入
? ? ? ? ?? ?方式一:urlpatterns += router.urls
? ? ? ? ? ? 方式二:(可以加前缀)
? ? ? ? ? ? urlpatterns = [
? ? ? ? ? ? ? ? path('', include(router.urls)),
? ? ? ? ? ? ]

# 继承ViewSetMixin的视图类中有其他方法,如何注册路由
? ?action装饰器:
? ? ? ? methods
? ? ? ? detail:加不加pk? ? ?# books/1/login
? ? ? ? url_path:='xx':books/xx? ? 如果不写,默认是方法名
? ? ? ? url_name:? 反向解析用
# 以后在视图类上 通过 self.action ?就能拿到当次请求的请求 action 方法名

class BookView(ReadOnlyModelViewSet): ?# list ?retrieve
? ? ? ? def get_queryset(self):
? ? ? ? ? ? if self.action=='list':
? ? ? ? ? ? ? ? return super().get_queryset()
? ? ? ? ? ? elif self.action=='xx':
? ? ? ? ? ? ? ? return Book.objects.all().filter(name__startswith="红")
? ? ? ? def get_serializer_class(self):
? ? ? ? ? ? # print('我一定会执行')
? ? ? ? ? ? # print(self.action)
? ? ? ? ? ? # return super().get_serializer_class()
? ? ? ? ? ? if self.action=='list':
? ? ? ? ? ? ? ? return 序列化所有的序列化类
? ? ? ? ? ? elif self.action=='retrieve':
? ? ? ? ? ? ? ? return 序列化单条的序列化类
? ? ? ? ? ? elif self.action=='login':
? ? ? ? ? ? ? ? return 序列化单条的序列化类

认证组件

# 登录功能
# 认证类:
? ? ?? ?1 写一个类,继承BaseAuthentication
? ? ? ? 2 重写 authenticate(self, request) 方法
? ? ? ? 3 在方法内部,根据用户携带的 数据【token】,判断是否登录[核心逻辑],如果登录就继续往后走[返回两个变量],如果没登录,抛异常,就不会往后走[视图的方法就不执行了]?

# 必须有token才能登录,通过token去user
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from .models import User, UserToken
class LoginAuth(BaseAuthentication):
    def authenticate(self, request):
        token = request.query_params.get('token')
        user_token = UserToken.objects.filter(token=token).first()
        # 当前登录用户
        if user_token:
            user = user_token.user
            return user, user_token
        else:
            raise AuthenticationFailed("您没有登录")

# 在视图类中使用 ---【这个视图类管理的所有方法,都会有登录认证的校验】

????????class BookDetailView(GenericViewSet):
? ? ?? ?????????????????authentication_classes = [LoginAuth

# 在配置文件中配置,所有接口都会有,包括登录接口

# setting.py
 REST_FRAMEWORK = {
? ? ? ? # 全局配置登录认证
? ? ? ? 'DEFAULT_AUTHENTICATION_CLASSES': ['app01.auth.LoginAuth']
? ? ?? ?}

# 局部禁用:
? ? ? class 视图类(APIView):
? ? ? ? ? ? authentication_classes = [ ]

?#? authenticate中如何判断是否登录:

class LoginAuth(BaseAuthentication):
? ? def authenticate(self, request):
? ? ? ? # 完成对用户的校验
? ? ? ? # 当次请求request
? ? ? ? token = request.query_params.get('token') or request.META.get('HTTP_TOKEN')
? ? ? ? # 表中校验
? ? ? ? user_token = UserToken.objects.filter(token=token).first()
? ? ? ? # 当前登录用户
? ? ? ? if user_token:
? ? ? ? ? ? user = user_token.user
? ? ? ? ? ? # 校验过后,返回两个值
? ? ? ? ? ? # return后,在后续的视图类的方法中 通过 request.user 就能取到当前登录用户
? ? ? ? ? ? # 如果不按这个规则来,后续request.user取不到当前登录用户
? ? ? ? ? ? return user, user_token
? ? ? ? else:
? ? ? ? ? ? raise AuthenticationFailed("您没有登录")

权限组件

# 访问某个接口有没有权限---》大部分情况下需要登录后再校验
# 使用方式跟认证雷同
# 写权限类? ? ?#?显示中文提示:self.message=中文
? ? ?? ?1 写一个类,继承BasePermission
? ? ? ? 2 重写 has_permission 方法
? ? ? ? 3 在方法内部,根据用户的 类型,判断有没有权限,如果有返回True,如果没有返回False
# 在视图类中使用 ---【这个视图类管理的所有方法,都会有权限控制】
? ? class BookDetailView(GenericViewSet):
? ? ? ? ? permission_classes = [CommonPermission]
# 在配置文件中配置,所有接口都会有,包括登录接口

setting.py
REST_FRAMEWORK = {
? # 全局配置登录认证
? 'DEFAULT_PERMISSION_CLASSES': ['']
}

# 局部禁用:
? ? ? class 视图类(APIView):
? ? ? ? ? ? permission_classes = [ ]
# 权限类代码
from rest_framework.permissions import BasePermission

# 只有超级管理员能访问,其他人都不能访问

class CommonPermission(BasePermission):
? ? def has_permission(self, request, view):
? ? ? ? # 到这,正常应该登录完了,登录完了 request.user 当前登录用户
? ? ? ? # 拿到用户后判断用户是否有权限--》用户表汇总用户类型字段 user_type--》根据类型判断权限
? ? ? ? try:
? ? ? ? ? ? user_type = request.user.user_type
? ? ? ? ? ? if user_type == 2:
? ? ? ? ? ? ? ? return True
? ? ? ? ? ? else:
? ? ? ? ? ? ? ? # user.get_字段名_display() ?返回这个字段的choice对应的文字
? ? ? ? ? ? ? ? self.message = '您是:%s,您没有权限操作这个' % request.user.get_user_type_display()
? ? ? ? ? ? ? ? return False
? ? ? ? except Exception as e:
? ? ? ? ? ? # 未登录用户也没有权限
? ? ? ? ? ? self.message = '您没有登录,您没有权限操作这个'
? ? ? ? ? ? return False

# 补充,后续的权限类,可能逻辑更复杂
? ? # 后续可能使用ACL权限控制,RBAC权限控制
? ? # 开直播 in [看视频]
? ? #开直播 in ?[看视频,收礼物,开直播]

频率组件

# 控制用户访问某个接口的频次,比如一分钟只能访问5次
# 使用步骤---跟上面有区别
?? ?1 写个类,继承 SimpleRateThrottle
? ? 2 重写方法:def get_cache_key(self, request, view): 返回什么就以什么做限制
? ? 3 写一个类属性:
? ? ?? ?rate = '5/minute' ? # second ?minute hour day
? ? ? ? rate = '5/m'
? ? ? ? rate = '5/d'
# 视图类上配置
? ? class BookView(ViewSetMixin, ListCreateAPIView):
? ? ? ? ? ? throttle_classes = [CommonThrottle]

# 全局配置--全局所有接口都会有频率限制

setting.py
?REST_FRAMEWORK = {
? ? 'DEFAULT_THROTTLE_CLASSES': ['app01.throttling.CommonThrottle'],
?? ?}

#? 局部禁用
? ? class BookView(ViewSetMixin, ListCreateAPIView):
? ? ? ? throttle_classes = [ ]

# 频率类代码

from rest_framework.throttling import BaseThrottle, SimpleRateThrottle
class CommonThrottle(SimpleRateThrottle):
? ? rate = '5/d'
? ? def get_cache_key(self, request, view):
? ? ? ? ip = request.META.get('REMOTE_ADDR')
? ? ? ? return ip ?# 返回什么,就以什么做频率限制(ip,用户id)

登录认证+权限+频率代码总结

# urls.py
from django.contrib import admin
from django.urls import path,include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/v1/', include('app01.urls')),
]

# app01\urls.py
from django.urls import path, include
from . import views
from rest_framework.routers import SimpleRouter, DefaultRouter

router = DefaultRouter()
router.register('users', views.UserView, 'users')
router.register('books', views.BookView, 'books')
router.register('books', views.BookDetailView, 'books')
urlpatterns = [
    path('', include(router.urls)),

]
views.py
from django.shortcuts import render

# Create your views here.

from rest_framework.decorators import action
from rest_framework.viewsets import ViewSet
from .models import User, UserToken
from rest_framework.response import Response
import uuid
from rest_framework.viewsets import ViewSetMixin, GenericViewSet
from rest_framework.generics import ListCreateAPIView, GenericAPIView
from rest_framework.mixins import CreateModelMixin, ListModelMixin, DestroyModelMixin, RetrieveModelMixin, \
    UpdateModelMixin
from .models import Book
from .serializer import BookSerializer
from .auth import LoginAuth

# 登录入口   1、拿到验证码
class UserView(ViewSet):
    authentication_classes = []
    permission_classes = []
    throttle_classes = []

    @action(methods=['POST'], detail=False)
    def login(self, request):
        username = request.data.get('username')
        password = request.data.get('password')
        user = User.objects.filter(name=username, password=password).first()
        if user:
            token = str(uuid.uuid4())
            UserToken.objects.update_or_create(defaults={'token': token}, user_id=user.pk)
            return Response({'code': '100', 'msg': '登录成功', 'token': token})
        else:
            return Response({'code': '101', 'msg': '用户名或密码错误'})

# 添加和查询所有
class BookView(ViewSetMixin, ListCreateAPIView):
    authentication_classes = [LoginAuth]  # 验证是否登录
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    def list(self, request, *args, **kwargs):
        print(request.user.name)
        print(request.auth)
        return super().list(request, *args, **kwargs)


class BookDetailView(GenericViewSet, DestroyModelMixin, RetrieveModelMixin, UpdateModelMixin):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
# auth.py
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from .models import UserToken

class LoginAuth(BaseAuthentication):
    def authenticate(self, request):
        token = request.query_params.get('token') or request.META.get('HTTP_TOKEN')
        user_token = UserToken.objects.filter(token=token).first()
        if user_token:
            user = user_token.user
            return user, user_token
        else:
            raise AuthenticationFailed("您没有登录")
# permission.py
from rest_framework.permissions import BasePermission
# 只有超级管理员能访问,其他人都不能访问
class CommonPermission(BasePermission):
    def has_permission(self, request, view):
        try:
            user_type = request.user.user_type
            if user_type == 2:
                return True
            else:
                # user.get_字段名_display()  返回这个字段的choice对应的文字
                self.message = '您是:%s,您没有权限操作这个' % request.user.get_user_type_display()
                return False
        except Exception as e:
            # 未登录用户也没有权限
            if 'login' in request.path:
                return True
            else:
                self.message = '您没有登录,您没有权限操作这个'
                return False
# throttling.py
from rest_framework.throttling import  SimpleRateThrottle

class CommonThrottle(SimpleRateThrottle):
    rate = '3/m'

    def get_cache_key(self, request, view):
        ip = request.META.get('REMOTE_ADDR')
        return ip
# setting.py
REST_FRAMEWORK = {
    # 全局配置登录认证
    'DEFAULT_AUTHENTICATION_CLASSES': ['app01.auth.LoginAuth'],    # 认证组件
    'DEFAULT_PERMISSION_CLASSES': ['app01.permission.CommonPermission'],   # 权限组件
    'DEFAULT_THROTTLE_CLASSES': ['app01.throttling.CommonThrottle'],   # 频率组件
}
# models.py

# Create your models here.
from django.db import models


class Book(models.Model):
    name = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5, decimal_places=2)

    publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
    authors = models.ManyToManyField(to='Author')

    @property
    def publish_detail(self):
        return {'name': self.publish.name, 'city': self.publish.city}

    @property
    def author_list(self):
        l = []
        for author in self.authors.all():
            l.append({'name': author.name, 'age': author.age})
        return l

    def __str__(self):
        return self.name


class Author(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    author_detail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE)

    def __str__(self):
        return self.name


class AuthorDetail(models.Model):
    telephone = models.BigIntegerField()
    birthday = models.DateField()
    addr = models.CharField(max_length=64)


class Publish(models.Model):
    name = models.CharField(max_length=32)
    city = models.CharField(max_length=32)
    email = models.EmailField(blank=True, null=True)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = '出版社'
        verbose_name_plural = verbose_name


#### 用户表,用来做登录
### 用户登录成功户,存登录状态
class User(models.Model):
    name = models.CharField(max_length=64)
    password = models.CharField(max_length=64)
    gender = models.CharField(max_length=64, default="男")
    # user_token = models.OneToOneField(to='UserToken')
    # 后续可以通过存的数字,取到文字
    user_type = models.IntegerField(default=0, choices=((0, '普通登录用户'), (1, '管理员'), (2, '超级管理员')))

class UserToken(models.Model):
    user = models.OneToOneField(to='User', on_delete=models.CASCADE)
    token = models.CharField(max_length=64)

# GET是查看 ,POST是拿数据

# 先POST通过/users/去生成token写在表里

? ? ? ? 再通过GET带上token去查看所有

权限组件源码分析

# 目标:
?? ?1 为什么写一个类继承BasePermission,重写has_permission
? ? ?? ?-可以不继承这个类,只重写这个方法也可以
? ? 2 权限类中 self.message ?会返回给前端
? ? 3 局部配置:放在视图类中:permission_classes = [CommonPermission]
? ? 4 全局配置,配置在配置文件中也可以--》视图类中就没有
? ? ?? ?就会使用:permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
? ? ? ? 优先从你项目的配置文件配置的DEFAULT_PERMISSION_CLASSES取,如果没有
? ? ? ? 就会去drf的配置文件DEFAULT_PERMISSION_CLASSES取
# 从哪里开始找?
?? ?继承APIView后,权限是在执行视图类的方法之前执行的
? ? 执行视图类的方法---》dispath中

def dispatch(self, request, *args, **kwargs):

        try:
            # 三大认证:认证,权限,频率
            self.initial(request, *args, **kwargs)
            ####执行视图类的方法开始###
            if request.method.lower() in self.http_method_names:
                handler = getattr(self, request.method.lower(),
                                  self.http_method_not_allowed)
            else:
                handler = self.http_method_not_allowed
            response = handler(request, *args, **kwargs)
            ####执行视图类的方法结束###
        except Exception as exc:
            response = self.handle_exception(exc)
        return self.response
    
#2 找到APIView的initial
    def initial(self, request, *args, **kwargs):
        self.perform_authentication(request)#认证
        self.check_permissions(request)#权限 
        self.check_throttles(request)#频率
        
# 3 self.check_permissions(request)---APIView
    def check_permissions(self, request):
        # self是 视图类的对象
        #self.get_permissions [CommonPermission(),]--->咱们配置的一个个权限类的对象,放到列表中
        # permission 权限类的对象
        for permission in self.get_permissions():
            # 咱们写的权限类,要重写has_permission,传了俩参数
            # 参数:request 是新的request
            # 参数:self 是?视图类的对象,就是咱么在视图类中写的self,它里面有
            # request和action等
            if not permission.has_permission(request, self):
                # 视图类的对象,没有权限
                self.permission_denied(
                    request,
                    # 从权限类的对象中反射了message,就是写的给前端看的文字
                    message=getattr(permission, 'message', None),
                    #响应状态码
                    code=getattr(permission, 'code', None)
                )
                
# 4 self.get_permissions() ---> APIView的
    def get_permissions(self):
        # 咱么视图类上配置的 permission_classes = [CommonPermission]
        # 返回值是 [CommonPermission(),]--->咱们配置的一个个权限类的对象,放到列表中
        return [permission() for permission in self.permission_classes]
    
    
# 5 self.permission_denied  --》APIView中
  def permission_denied(self, request, message=None, code=None):
        if request.authenticators and not request.successful_authenticator:
            raise exceptions.NotAuthenticated()
        # 抛了异常,会被全局异常捕获,detai会放在响应体中,code会放在响应状态码中
        raise exceptions.PermissionDenied(detail=message, code=code)

认证类源码分析

# 继承APIView后,权限是在执行视图类的方法之前执行的
? ?执行视图类的方法---》dispath中? ? ? ??

def dispatch(self, request, *args, **kwargs):

? ? ? ? try:
? ? ? ? ? ? # 三大认证:认证,权限,频率
? ? ? ? ? ? self.initial(request, *args, **kwargs)
? ? ? ? ? ? ####执行视图类的方法开始###
? ? ? ? ? ? if request.method.lower() in self.http_method_names:
? ? ? ? ? ? ? ? handler = getattr(self, request.method.lower(),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? self.http_method_not_allowed)
? ? ? ? ? ? else:
? ? ? ? ? ? ? ? handler = self.http_method_not_allowed
? ? ? ? ? ? response = handler(request, *args, **kwargs)
? ? ? ? ? ? ####执行视图类的方法结束###
? ? ? ? except Exception as exc:
? ? ? ? ? ? response = self.handle_exception(exc)
? ? ? ? return self.response
? ??
#2 找到APIView的initial
? ? def initial(self, request, *args, **kwargs):
? ? ? ? self.perform_authentication(request)#认证
? ? ? ? self.check_permissions(request)#权限?
? ? ? ? self.check_throttles(request)#频率
? ? ? ??
# 3 self.perform_authentication(request)
? def perform_authentication(self, request):
? ? ? ? request.user # 新的request对象
? ? ? ??
? ? ? ??
# 4 Request类中找 user 方法包装成了数据属性
?? ?from rest_framework.request import Request
? ? @property
? ? def user(self):
? ? ? ? if not hasattr(self, '_user'):
? ? ? ? ? ? with wrap_attributeerrors():
? ? ? ? ? ? ? ? # self是 新的request对象
? ? ? ? ? ? ? ? self._authenticate() # 一开始没有,就走了self._authenticate()
? ? ? ? return self._user
? ??
? ??
# 5 ?Request类中找_authenticate()
? ? def _authenticate(self):
? ? ? ? # 拿出你配置在视图类上一个个认证类的对象 ?LoginAuth()
? ? ? ? # authenticator就是LoginAuth()
? ? ? ? for authenticator in self.authenticators:
? ? ? ? ? ? try:
? ? ? ? ? ? ? ? # 为什么咱么要重写 authenticate
? ? ? ? ? ? ? ? #self是谁?request就是认证类的 def authenticate(self, request):
? ? ? ? ? ? ? ? # 正常返回两个值:return user, user_token
? ? ? ? ? ? ? ? # 如果抛了异常:AuthenticationFailed--》捕获了APIException
? ? ? ? ? ? ? ? user_auth_tuple = authenticator.authenticate(self)
? ? ? ? ? ? except exceptions.APIException:
? ? ? ? ? ? ? ? self._not_authenticated()
? ? ? ? ? ? ? ? raise
? ? ? ? ? ? if user_auth_tuple is not None:#正常返回了两个值
? ? ? ? ? ? ? ? self._authenticator = authenticator
? ? ? ? ? ? ? ? # 解压赋值:self是request
? ? ? ? ? ? ? ? #后续在视图类中 request.user 就是当前登录用户
? ? ? ? ? ? ? ? self.user, self.auth = user_auth_tuple
? ? ? ? ? ? ? ? return
? ? ? ? self._not_authenticated()

# ?咱们视图类中得认证类可以配置多个
?? ?-如果 第一个认证类,就返回了两个值
? ? -后续的认证类就不走了
? ? -如果认证类中要返回两个值,视图类中配了多个---》把返回两个值的放在最后
? ? -返回的两个值,第一个给了request.user,第一个给了request.auth,后续视图类中可以取出来

# self.authenticators ---》 Request中
# Request类实例化得到对象,传入authenticators 最终给了
def __init__(self, request, parsers=None, authenticators=None,negotiator=None, parser_context=None):
??? ?self.authenticators = authenticators or ()
? ??
? ??
# 8 哪里对Request类实例化了? APIView中
APIView 中dispatch中---》包装了新的request
request = self.initialize_request(request, *args, **kwargs)
def initialize_request(self, request, *args, **kwargs):
? ? ? ? return Request(
? ? ? ? ? ? request,
? ? ? ? ? ? parsers=self.get_parsers(),
? ? ? ? ? ? authenticators=self.get_authenticators(),
? ? ? ? ? ? negotiator=self.get_content_negotiator(),
? ? ? ? ? ? parser_context=parser_context
? ? ? ? )
? ? ? ??
? ? ? ??
# 9 self.get_authenticators() ?在APIView中 self是视图类的对象
? ? def get_authenticators(self):
? ? ? ? return [auth() for auth in self.authentication_classes]

今日思维导图:

文章来源:https://blog.csdn.net/qq_48064830/article/details/135222718
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。