drf之自定义User表与自定义认证类
自定义user表签发token
普通写法,写在view类中
from rest_framework.views import APIView # class UserView(APIView): # 自动生成路由, from rest_framework.viewsets import ViewSetMixin from rest_framework.decorators import action from rest_framework.generics import GenericAPIView from .models import UserInfo from .serializer import UserInfoSerializer from rest_framework.response import Response from rest_framework_jwt.settings import api_settings jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER # /user/login/--->post请求 # class UserView(ViewSetMixin, APIView): # @action(methods=['POST'], detail=False) # def login(self, request): # res_dic = {'code': 100, 'msg': '成功'} # username = request.data.get('username') # password = request.data.get('password') # user = UserInfo.objects.filter(username=username, password=password).first() # if user: # 登陆成功 # # 签发token?如何签发?--》去jwt源码中扣 # payload = jwt_payload_handler(user) # 得到荷载--》字典 # print(payload) # token = jwt_encode_handler(payload) # 通过荷载得到token串 # res_dic['token'] = token # res_dic['username'] = user.username # return Response(res_dic) # else: # res_dic['code'] = 101 # res_dic['msg'] = '用户名或密码错误' # return Response(res_dic)
逻辑写在序列化类中
视图函数
# 换种写法,写上面的登录,所有校验规则,写在序列化类中---》这种用的多 class UserView(ViewSetMixin, APIView): @action(methods=['POST'], detail=False) def login(self, request): res_dic = {'code': 100, 'msg': '成功'} ser = UserInfoSerializer(data=request.data,context={'request':request}) if ser.is_valid(): # 这句话会走:字段自己的校验规则,局部钩子,全局钩子 token = ser.context.get('token') username = ser.context.get('username') # token = ser.token # username = ser.username res_dic['token'] = token res_dic['username'] = username else: res_dic['code'] = 101 res_dic['msg'] = ser.errors return Response(res_dic)
序列化类
class UserInfoSerializer(serializers.ModelSerializer): class Meta: model = UserInfo fields = ['username', 'password'] # 根据表模型中写的,字段自己有校验规则 def validate(self, attrs): # 打印请求方式? print(self.context.get('request').method) # 签发token逻辑,签发生成token,放到ser.context字典中 username = attrs.get('username') password = attrs.get('password') user = UserInfo.objects.filter(username=username, password=password).first() if user: # 登陆成功 payload = jwt_payload_handler(user) # 得到荷载--》字典 token = jwt_encode_handler(payload) # 通过荷载得到token串 # serializer和视图类沟通的桥梁 self.context['token'] = token self.context['username'] = user.username # self.token=token # self.username=username else: raise ValidationError('用户名或密码错误') return attrs
自定义认证类
from rest_framework.authentication import BaseAuthentication from rest_framework_jwt.settings import api_settings from rest_framework.exceptions import AuthenticationFailed import jwt # from django.utils.translation import ugettext as _ from .models import UserInfo jwt_decode_handler = api_settings.JWT_DECODE_HANDLER class JWTAuthentication(BaseAuthentication): def authenticate(self, request): # 第一步:取出传入的token--》从哪去?--》咱们定的:请求地址?请求头? # token=request.query_params.get('token')# 请求地址? # http请求头中的数据,在META中,统一变成 HTTP_请求头的key大写 jwt_value=request.META.get('HTTP_TOKEN') if jwt_value: # 验证token:是否过期,是否被篡改--》去源码扣 try: payload = jwt_decode_handler(jwt_value) except jwt.ExpiredSignature: msg = '签名过期' raise AuthenticationFailed(msg) except jwt.DecodeError: msg = '签名被篡改' raise AuthenticationFailed(msg) except jwt.InvalidTokenError: raise AuthenticationFailed('未知错误') # 通过payload获得当前登录用户 user = UserInfo.objects.filter(pk=payload['user_id']).first() return (user, jwt_value) else: raise AuthenticationFailed('您没有携带token')
# django-admin混合开发--》后台管理---》美化--》simpleui # 使用步骤: -安装:pip3 install django-simpleui -注册app INSTALLED_APPS = [ 'simpleui', ] -定制左侧菜单 SIMPLEUI_CONFIG = { 'system_keep': False, 'menu_display': ['监控大屏','应用1', '权限认证', '测试', '动态菜单测试'], # 开启排序和过滤功能, 不填此字段为默认排序和全部显示, 空列表[] 为全部不显示. 'dynamic': True, # 设置是否开启动态菜单, 默认为False. 如果开启, 则会在每次用户登陆时动态展示菜单内容 'menus': [ { 'name': '监控大屏', 'icon': 'fas fa-code', 'url': '/index/' }, { 'app': 'app01', 'name': '应用1', 'icon': 'fas fa-user-shield', 'models': [ { 'name': '图书', 'icon': 'fa fa-user', 'url': 'app01/book/' }, { 'name': '用户', 'icon': 'fa fa-user', 'url': 'app01/userinfo/' } ] }, { 'app': 'auth', 'name': '权限认证', 'icon': 'fas fa-user-shield', 'models': [ { 'name': '用户', 'icon': 'fa fa-user', 'url': 'auth/user/' }, { 'name': '用户组', 'icon': 'fa fa-user', 'url': 'auth/group/' } ] }, { # 自2021.02.01+ 支持多级菜单,models 为子菜单名 'name': '测试', 'icon': 'fa fa-file', # 二级菜单 'models': [{ 'name': 'Baidu', 'icon': 'far fa-surprise', # 第三级菜单 , 'models': [ { 'name': '爱奇艺', 'url': 'https://www.iqiyi.com/dianshiju/' # 第四级就不支持了,element只支持了3级 }, { 'name': '百度问答', 'icon': 'far fa-surprise', 'url': 'https://zhidao.baidu.com/' } ] }, { 'name': '内网穿透', 'url': 'https://www.wezoz.com', 'icon': 'fab fa-github' }] }, { 'name': '动态菜单测试', 'icon': 'fa fa-desktop', 'models': [{ 'name': time.time(), 'url': 'http://baidu.com', 'icon': 'far fa-surprise' }] } ] } -自带权限 -自定义左侧菜单的页面显示 -通过混合开发,编写路径,配置到上面即可 -更多操作见官方
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通