标签:rtc class shortcut 14. char short inview views hid
首先我们需要先了解一下CBV的执行流程:
通常在写CBV模式时,会在路由匹配时re_path(‘login/‘, views.LoginView.as_view()),进入as_view() 中发现最后返回的是view,然后又发现view函数中最后返回的是dispatch(),进入该函数发现,其实其中就是通过反射执行request.method对应的方法。总结,CBV本质是通过执行反射进行的。而且在执行对应方法之前会执行dispatch().
当我们的视图对应的类继承的是rest_framework.views 的APIView时,我们进入dispatch(),发现request = self.initialize_request(request, *args, **kwargs)中最后返回的是Request的对象,对原生request进行封装(进入Request发现原生的request为_request),并且添加了如authenticators=self.get_authenticators()等属性,进入get_authenticators()返回的是authentication_classes的实例对象,进而发现默认authentication_classes是对读配置文件的。
ok,我们继续看dispatch(),在封装之后又self.initial(request, *args, **kwargs),initial中又走self.perform_authentication(request),该方法返回了request.user,这时的request是最开始封装的request,查看Requet其中的user,发现走了self._authenticate(),其中对self.authenticators进行循环,执行对应的authenticate()。
from django.db import models # Create your models here. class UserInfo(models.Model): username = models.CharField(max_length=16) password = models.CharField(max_length=32) type = models.SmallIntegerField( choices=((1, ‘普通用户‘), (2, ‘VIP用户‘)), default=1 ) class Token(models.Model): user = models.OneToOneField(to=‘UserInfo‘,on_delete=models.CASCADE) token_code = models.CharField(max_length=128)
from django.shortcuts import render,HttpResponse from app01 import models from django.views import View from rest_framework.views import APIView from rest_framework.authentication import BaseAuthentication from rest_framework.exceptions import AuthenticationFailed from django.http import JsonResponse # Create your views here. def get_random_token(username): """ 根据用户名和时间戳生成随机token :param username: :return: """ import hashlib, time timestamp = str(time.time()) m = hashlib.md5(bytes(username, encoding="utf8")) # 加盐 m.update(bytes(timestamp, encoding="utf8")) return m.hexdigest() # 自定义认证类 class MyAuth(BaseAuthentication): def authenticate(self,request): try: token = request._request.GET.get(‘token‘) token_obj = models.Token.objects.get(token_code=token) if token_obj: return (token_obj.user, token_obj) else: raise AuthenticationFailed(‘认证失败‘) except Exception as e: raise AuthenticationFailed(‘请携带token,认证失败‘) class LoginView(APIView): """ 校验用户名密码是否正确从而生成token的视图 """ authentication_classes = [MyAuth, ] def post(self, request): # self.dispatch() res = {"code": 0} username = request.data.get("username") password = request.data.get("password") user = models.UserInfo.objects.filter(username=username, password=password).first() if user: # 如果用户名密码正确 token = get_random_token(username) # 找到user对象,有就更新(更新token_code),没有就创建 models.Token.objects.update_or_create(defaults={"token_code": token}, user=user) res["token"] = token else: res["code"] = 1 res["error"] = "用户名或密码错误" return JsonResponse(res) def get(self,request): return HttpResponse(‘get‘)
如果我们自己写了authentication_classes,那么就会走我们写在其中的类的实例对象,我自定义认证类中必须写有authenticate()实现认证逻辑。
re_path(‘login/‘, views.LoginView.as_view())
标签:rtc class shortcut 14. char short inview views hid
原文地址:https://www.cnblogs.com/zhaowei5/p/10331242.html