首页 > 其他分享 >登录注册

登录注册

时间:2023-03-05 14:34:19浏览次数:38  
标签:username 登录 get mobile token user 注册 import

登录、注册功能分析

# 接口分析
1 校验手机号是否存在接口
2 多方式登录接口:用户名/手机号/邮箱 + 密码都可以登录
3 发送手机验证码接口(借助于第三方短信平台)
4 短信登录接口
5 注册接口

校验手机号是否存在接口

视图类

视图类初级版

from .models import User
from rest_framework.viewsets import GenericViewSet
from rest_framework.decorators import action
from utils.common_response import APIResponse

class UserView(GenericViewSet):
    @action(methods=['post'],detail=False)
    def send_sms(self,request,*args,**kwargs):
        mobile = request.query_params.get('mobile')
        if mobile:
            user=User.objects.filter(mobile=mobile).first()
            if user:
                return APIResponse(code=100,msg='手机号存在',exist=True)
            else:
                return APIResponse(code=100, msg='手机号不存在',exist=False)
        else:
            return APIResponse(code=999,msg='手机号必填')
            

视图类代码优化方案一

因为已经做了全局异常处理,主动抛异常也可以,抛异常不是return,而是raise

from .models import User
from rest_framework.viewsets import GenericViewSet
from rest_framework.decorators import action
from utils.common_response import APIResponse
from rest_framework.exceptions import APIException
from .serilizer import UserLoginSerializer

class UserView(GenericViewSet):
    serializer_class = UserLoginSerializer
    queryset = User.objects.filter(is_active=True).all()

    @action(methods=['get'],detail=False)
    def send_sms(self,request,*args,**kwargs):
        try:
            mobile = request.GET.get('mobile')
            if mobile:
                # 用get方法来查询一个数据库里不存在的记录,程序会报错,我们做了全局异常处理,这里会被捕获
                User.objects.get(mobile=mobile)
            else:
                raise APIException('手机号必填')
        except Exception as e:
            return APIResponse(code=777,msg=str(e))
        return APIResponse(code=100, msg='手机号存在')

视图类代码优化方案二

class UserView(GenericViewSet):
    serializer_class = UserLoginSerializer
    queryset = User.objects.filter(is_active=True).all()

    @action(methods=['get'], detail=False)
    def send_sms(self, request, *args, **kwargs):
        try:
            mobile = request.GET.get('mobile')
            User.objects.get(mobile=mobile)
        except Exception as e:
            return APIResponse(code=777, msg=str(e))
        return APIResponse(code=100, msg='手机号存在')

路由

总路由

from django.urls import path,include
path('api/v1/user/',include('home.urls'))

子路由

from rest_framework.routers import SimpleRouter
from . import views

router = SimpleRouter()
# 访问 http://127.0.0.1:8000/api/v1/user/userinfo/send_sms
router.register('userinfo', views.UserView, 'userinfo')

urlpatterns = [

]

urlpatterns += router.urls

多方式登录接口

逻辑分析

1.取出前端传入的用户名和密码
2.通过用户名和密码去数据库查询用户
3.如果查询到,签发token
4.返回给前端登录成功

序列化类

import re
from .models import User
from rest_framework import serializers
from rest_framework.exceptions import APIException

from rest_framework_jwt.settings import api_settings
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

# 这个序列化类用来校验字段,不用来做序列化和反序列化
class UserLoginSerializer(serializers.ModelSerializer):
    # 重写username字段,把原来的校验规则去掉
    username = serializers.CharField()
    class Meta:
        model = User
        # username映射过来,是唯一的,字段自己的校验就过不了
        fields = ['username','password']

    def validate(self, attrs):
        """
        1.取出前端传入的用户名和密码
        2.通过用户名和密码去数据库查询用户
        3.如果查询到,签发token
        4.返回给前端登录成功
        """
        # attrs是前端传入的数据,经过字段自己校验和局部钩子校验过后的数据
        user=self._get_user(attrs)
        token=self._get_token(user)
        # 把用户名和token放到ser的context中
        self.context['token']=token
        self.context['username']=user.username
        return attrs


    def _get_user(self,attrs):
        username=attrs.get('username')
        password=attrs.get('password')
        if re.match(r'^1[3-9][0-9]{9}$',username):
            user = User.objects.filter(mobile=username).first()
        elif re.match(r'^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$',username):
            user=User.objects.filter(email=username).first()
        else:
            user = User.objects.filter(username=username).first()
        if user and user.check_password(password):
            return user
        else:
            # 用户不存在或密码错误   这里的代码,还是在全局钩子中执行,全局钩子校验失败,要抛异常,所以在这抛异常
            raise APIException('用户不存在或密码错误')


    def _get_token(self,user):
        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)
        return token

视图类

class UserView(GenericViewSet):
    queryset = User.objects.filter(is_active=True).all()
    serializer_class = UserLoginSerializer
    
    @action(methods=['POST'],detail=False)
    def login_mul(self,request):
        # 序列化类对象时,可以传入context字典
        # context是视图类和序列化类沟通的桥梁
        # 有了序列化类对象,通过对象.context就可以拿到值
        ser = self.get_serializer(data=request.data)
        ser.is_valid(raise_exception=True)  # 执行这句话,会执行字段自己校验,局部钩子、全局钩子
        token=ser.context.get('token')
        username = ser.context.get('username')
        return APIResponse(token=token,username=username)

 

标签:username,登录,get,mobile,token,user,注册,import
From: https://www.cnblogs.com/chen-ao666/p/17180515.html

相关文章