DRF实现多方式登录

该文章介绍了如何在DjangoRestFramework中创建一个登录视图集,使用ViewSet自定义路由映射并结合序列化器实现用户登录功能。LoginSerializer覆盖了系统字段以适应多方式登录(手机、邮箱、账号),并利用JWT进行身份验证和生成令牌。
摘要由CSDN通过智能技术生成

views:

from rest_framework.response import Response
from rest_framework.viewsets import ViewSet

from .serializer import LoginSerializer


class LoginViewSet(ViewSet):
    # 需要和mixins结合使用,继承GenericViewSet,不需要则继承ViewSet
    # 为什么继承视图集,不去继承工具视图或视图基类,因为视图集可以自定义路由映射:
    #       可以做到get映射get,get映射list,还可以做到自定义(灵活)
    def login(self, request, *args, **kwargs):
        serializer = LoginSerializer(data=request.data, context={'request': request})
        serializer.is_valid(raise_exception=True)
        token = serializer.context.get('token')
        return Response({'code': 100, 'msg': '登录成功', "token": token})

serializer:

from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from rest_framework_jwt.serializers import jwt_encode_handler, jwt_payload_handler

from .models import User


# 重点:自定义login,完成多方式登录
class LoginSerializer(serializers.ModelSerializer):
    # 登录请求,走的是post方法,默认post方法完成的是create入库校验,所以唯一约束的字段,会进行数据库唯一校验,导致逻辑相悖
    # 需要覆盖系统字段,自定义校验规则,就可以避免完成多余的不必要校验,如唯一字段校验
    username = serializers.CharField()

    class Meta:
        model = User
        # 结合前台登录布局:采用账号密码登录,或手机密码登录,布局一致,所以不管账号还是手机号,都用username字段提交的
        fields = ('username', 'password')

    def validate(self, attrs):
        # 在全局钩子中,才能提供提供的所需数据,整体校验得到user
        # 再就可以调用签发token算法,将user信息转换为token
        # 将token存放到context属性中,传给外键视图类使用
        user = self._get_user(attrs)
        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)
        self.context['token'] = token
        return attrs

    # 多方式登录
    def _get_user(self, attrs):
        username = attrs.get('username')
        password = attrs.get('password')
        import re
        if re.match(r'^1[3-9][0-9]{9}$', username):
            # 手机登录
            user = User.objects.filter(phone=username, is_active=True).first()
        elif re.match(r'^.+@.+$', username):
            # 邮箱登录
            user = User.objects.filter(email=username, is_active=True).first()
        else:
            # 账号登录
            user = User.objects.filter(username=username, is_active=True).first()
        if user and user.check_password(password):
            return user

        raise ValidationError({'user': 'user error'})

utils:

import re
from .models import User
from django.contrib.auth.backends import ModelBackend


class JWTModelBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        try:
            if re.match(r'^1[3-9]\d{9}$', username):
                user = User.objects.get(mobile=username)
            else:
                user = User.objects.get(username=username)
        except User.DoesNotExist:
            return None
        if user.check_password(password) and self.user_can_authenticate(user):
            return user

urls:

from django.contrib import admin
from django.urls import path
from app01 import views


urlpatterns = [
    path('admin/', admin.site.urls),

    path('login/', views.LoginViewSet.as_view({'post':'login'}))
]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值