码迷,mamicode.com
首页 > 其他好文 > 详细

(生鲜项目)17. drf实现发送短信验证码功能

时间:2019-12-28 11:39:56      阅读:119      评论:0      收藏:0      [点我收藏+]

标签:登录   需要   ida   写代码   objects   字典   gis   port   div   

第一步; 前期分析

由于之前在设计model的时候, 我们已经决定对code进行数据库保存, 所以这里我们应该使用 mixins.CreateModelMixin

同时, 用户发过来的手机号码, 我们在后端应该执行自己的验证, 包括

  • 手机号码是否被注册
  • 手机号码是否合法  [在settings.py中加上 REGEX_MOBILE="^1[358]\d{9}$|^147\d{8}$|^176\d{8}$"]
  • 两次验证码的间隔是否大于60秒

基于以上考虑, 我们需要创建一个 serializers 

在写serializers逻辑的时候, 要注意这里我们不能像之前写goods那样, 把serializers和users.models.VerifyCode绑定起来, 因为VerifyCode的code是必填字段, 但是用户获取验证码只需要手机号码即可

如果要单独使用serializers并对其中的某个字段进行验证, 需要重写validate_字段名()函数

验证码code应该在发送成功之后再保存, 以防止用户猜到了code, 而登录成功

 

第二步; 写代码

首先写user.serializers.py

import re
from datetime import datetime, timedelta
from rest_framework import serializers
from django.contrib.auth import get_user_model  

from MxShop.settings import REGEX_MOBILE
from .models import VerifyCode

User = get_user_model() # 可以获取数据库的userprofile表


# 验证手机号码
class SmsSerializer(serializers.Serializer):
    mobile = serializers.CharField(max_length=11)

    # 单独对mobile字段进行验证
    def validate_mobile(self, mobile):
        # 手机号是否注册
        if User.objects.filter(mobile=mobile).count():
            raise serializers.ValidationError("用户已经存在")

        # 手机号码是否合法
        if not re.match(REGEX_MOBILE, mobile):
            raise serializers.ValidationError("手机号码非法")

        # 验证发送频率
        one_minute_ago = datetime.now() - timedelta(hours=0, minutes=1, seconds=0)
        if VerifyCode.objects.filter(add_time__gt=one_minute_ago, mobile=mobile).count():
            raise serializers.ValidationError("距离上一次发送未超过60s")

        # 验证通过
        return mobile

然后写user.views.py

from django.shortcuts import render
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_model
from django.db.models import Q
from rest_framework.mixins import CreateModelMixin
from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework import status
from random import choice

from .serializers import SmsSerializer
from utils.yunpian import YunPian
from MxShop.settings import APIKEY
from .models import VerifyCode

User = get_user_model()# 发送短信验证码
class SmsCodeViewset(CreateModelMixin,viewsets.GenericViewSet):
    serializer_class = SmsSerializer

    # 生成随机验证码的函数
    def generate_code(self):
        seeds="1234567890"
        code_lst=[]
        for i in range(4):
            code_lst.append(choice(seeds))
        return "".join(code_lst)


    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True) # 如果serializer不通过, 那么后面就不会执行,而且drf会自动封装400的状态码

        # 上面的mobile字段校验成功后,获取mobile, 并对其发送验证码
        mobile=serializer.validated_data["mobile"] # validated_data就是serializer返回的数据, 是一个字典
        yunpian = YunPian(APIKEY)
        code=self.generate_code()
        sms_status = yunpian.send_sms(code=code,mobile=mobile)

        # 如果发送失败,把错误信息填充给mobile,同时封装一个400的状态码
        if sms_status["code"] != 0:
            return Response(
                {"mobile":sms_status["msg"]},
                status=status.HTTP_400_BAD_REQUEST
            )
        else: # 如果发送成功就先保存code到数据库, 然后返回手机号码,并封装201状态码
            code_record=VerifyCode(code=code,mobile=mobile)
            code_record.save()
            return Response(
                {"mobile":mobile},
                status=status.HTTP_201_CREATED
            )

然后是settings.py

# 手机号码正则表达式
REGEX_MOBILE="^1[358]\d{9}$|^147\d{8}$|^176\d{8}$"

# 云片网设置
APIKEY = "cdb6f4b3860c552f790176a9e4f3fd85"

最后是urls.py, 注册一个验证码接口

# 发送验证码的接口
router.register(rcode, SmsCodeViewset, basename="code")

然后去浏览器测试

技术图片

 

 技术图片

 

 技术图片

 

 

 

 

 

 

 

 

---  君子处其实,不处其华;治其内,不治其外   张居正  ----

(生鲜项目)17. drf实现发送短信验证码功能

标签:登录   需要   ida   写代码   objects   字典   gis   port   div   

原文地址:https://www.cnblogs.com/jiangzongyou/p/12111093.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!