DRF实现发送短信验证码接口
一、settings.py
# 手机号码正则表达式 REGEX_MOBILE = "^1[358]\d{9}$|^147\d{8}$|^176\d{8}$"
二、users下新建serializers.py,代码如下:
# users/serializers.py import re from datetime import datetime, timedelta from MxShop.settings import REGEX_MOBILE from users.models import VerifyCode from rest_framework import serializers from django.contrib.auth import get_user_model User = get_user_model() class SmsSerializer(serializers.Serializer): mobile = serializers.CharField(max_length=11) #函数名必须:validate + 验证字段名 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("手机号码非法") # 验证码发送频率 #60s内只能发送一次 one_mintes_ago = datetime.now() - timedelta(hours=0, minutes=1, seconds=0) if VerifyCode.objects.filter(add_time__gt=one_mintes_ago, mobile=mobile).count(): raise serializers.ValidationError("距离上一次发送未超过60s") return mobile
三、APIKEY加到settings里面
#云片网APIKEY APIKEY = "xxxxx327d4be01608xxxxxxxxxx"
四、views后台逻辑
我们要重写CreateModelMixin的create方法,下面是源码:
class CreateModelMixin(object): """ Create a model instance. """ def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) self.perform_create(serializer) headers = self.get_success_headers(serializer.data) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) def perform_create(self, serializer): serializer.save() def get_success_headers(self, data): try: return {'Location': str(data[api_settings.URL_FIELD_NAME])} except (TypeError, KeyError): return {}
需要加上自己的逻辑
users/views.py
from rest_framework.mixins import CreateModelMixin from rest_framework import viewsets from .serializers import SmsSerializer from rest_framework.response import Response from rest_framework import status from utils.yunpian import YunPian from MxShop.settings import APIKEY from random import choice from .models import VerifyCode class SmsCodeViewset(CreateModelMixin,viewsets.GenericViewSet): ''' 手机验证码 ''' serializer_class = SmsSerializer def generate_code(self): """ 生成四位数字的验证码 """ seeds = "1234567890" random_str = [] for i in range(4): random_str.append(choice(seeds)) return "".join(random_str) def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) #验证合法 serializer.is_valid(raise_exception=True) mobile = serializer.validated_data["mobile"] yun_pian = YunPian(APIKEY) #生成验证码 code = self.generate_code() sms_status = yun_pian.send_sms(code=code, mobile=mobile) if sms_status["code"] != 0: return Response({ "mobile": sms_status["msg"] }, status=status.HTTP_400_BAD_REQUEST) else: code_record = VerifyCode(code=code, mobile=mobile) code_record.save() return Response({ "mobile": mobile }, status=status.HTTP_201_CREATED)
云片网单条短信发送的使用说明:
五、配置url
from users.views import SmsCodeViewset # 配置codes的url router.register(r'code', SmsCodeViewset, base_name="code")