利用腾讯云和drf框架去编写一个用户注册的验证码验证

一、编写利用腾讯云文件

在项目—>utils下创建一个文件tencentsms.py:

class TengXun(object):

    def send_sms(self, code, mobile):
        # 短信应用SDK AppID
        appid = APP_ID  # SDK AppID是1400开头,你们申请的appid

        # 短信应用SDK AppKey 也是你们自己的
        appkey = APP_KEY

        # 需要发送短信的手机号码
        phone_numbers = "{mobile}".format(mobile=mobile)

        # 短信模板ID,需要在短信应用中申请
        template_id = TEMPLATE_ID

        # 签名
        sms_sign = "你们自己签名的内容"  # NOTE: 这里的签名"腾讯云"只是一个示例,真实的签名需要在短信控制台中申请,另外签名参数使用的是`签名内容`,而不是`签名ID`

        ssender = SmsSingleSender(appid, appkey)
        params = ["{code}".format(code=code), "3"]  # 当模板没有参数时,`params = []`
        try:
            result = ssender.send_with_param(86, phone_numbers, template_id, params, sign=sms_sign, extend="",ext="")  # 签名参数未提供或者为空时,会使用默认签名发送短信
        except HTTPError as e:
            print(e)
        except Exception as e:
            print(e)
        print(result)
        return result

二、DRF实现用户注册

1.在settings中设置手机号的正则:

		# 手机号码正则表达式
		REGEX_MOBILE = r"^1[3-9]\d{9}$"

当然可能你也可以把腾讯云的那些内容放在自己的本地设置里面安全一点。
2.接下来写我们的数据库表,

from datetime import datetime
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import AbstractUser

class CustomUser(AbstractUser):
    """用户"""

	    name = models.CharField(max_length=30, null=True, blank=True, verbose_name="姓名")
	    mobile = models.CharField(max_length=11, verbose_name="电话")
	
	    class Meta:
	        verbose_name_plural = verbose_name = "用户(CustomUser)"
	        ordering = ('id',)
	
	    def __str__(self):
	        return self.username


class VerifyCode(models.Model):
    """
    短信验证
    """
    code = models.CharField(max_length=10, verbose_name="验证码")
    mobile = models.CharField(max_length=11, verbose_name="电话")

    add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")

    class Meta:
        verbose_name = "短信验证码"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.code

接着在serserializer.py中设置序列化格式,并进行检验:

import re
from rest_framework import serializers
from django.contrib.auth import authenticate
from django.contrib.auth import get_user_model
from datetime import datetime
from datetime import timedelta
from django.utils.timezone import now
from rest_framework.validators import UniqueValidator

from .models import *

from mysite.settings import REGEX_MOBILE


class CustomUserSerializer(serializers.ModelSerializer):
class Meta:
    model = CustomUser
    fields = (
        'url',
        'id',
        'username',
    )


User = get_user_model()


class SmsSerializer(serializers.Serializer):
    mobile = serializers.CharField(max_length=11)

def validate_mobile(self, mobile):
    """
    验证手机号码
    :param data:
    :return:
    """

    # 手机是否注册
    # if User.objects.filter(mobile=mobile).count() != 0:
    #     raise serializers.ValidationError("用户已经存在")

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

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

    return mobile

3.接下来写的view函数

	# from rest_framework_jwt.serializers import jwt_payload_handler
	# from rest_framework_jwt.utils import jwt_encode_handler
	
	from .models import *
	from .serializers import *
	from common.views import CommonViewSet
	from common.permissions import IsYourself
	
	# from utils.tencentsms import send_sms_single
	
	from django.contrib.auth.backends import ModelBackend
	from django.contrib.auth import get_user_model
	from random import choice
	from rest_framework.mixins import CreateModelMixin
	from rest_framework import viewsets
	from rest_framework.response import Response
	from rest_framework import status
	
	from utils.tencentsms import TengXun
	
	
	
	
	
	class CustomUserViewSet(
	    CommonViewSet,
	    mixins.ListModelMixin,
	    mixins.RetrieveModelMixin,
	    mixins.UpdateModelMixin,
	    viewsets.GenericViewSet
	):
	    """
	    list:
	        返回所有用户
	    retrieve:
	        返回一个用户
	    update:
	        更新用户信息
	    partial_update:
	        部分更新用户信息
	    """
	
	    queryset = User.objects.all()
	    serializer_class = CustomUserSerializer
	    filter_backends = (filters.SearchFilter,)
	    search_fields = ['nickname', 'intro']
	    permission_classes_by_action = {
	        'list': [IsAuthenticated, IsYourself],
	        'retrieve': [IsAuthenticated, IsYourself],
	        'update': [IsAuthenticated, IsYourself],
	        'partial_update': [IsAuthenticated, IsYourself],
	    }
	#这是我的权限设置你们可以删除或者写上自己的
	
	class SmsCodeViewset(CreateModelMixin, viewsets.GenericViewSet):
	    """
	    发送短信验证码
	    """
	    serializer_class = SmsSerializer
	
	    def generate_code(self):
	        """
	        生成四位数字的验证码
	        :return:
	        """
	        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"]
	
	        teng_xun = TengXun()
	
	        code = self.generate_code()
	
	        sms_status = teng_xun.send_sms(code=code, mobile=mobile)
	
	        if sms_status["result"] != 0:
	            return Response({
	                "mobile": sms_status["errmsg"]
	            }, 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)
	
	
	class UserViewSet(CreateModelMixin, viewsets.GenericViewSet):
	    """
	    用户
	    """
	    serializer_class = UserRegSerializer
	    queryset = User.objects.all()
	
	    # 重新定义create函数 实现注册后自动登录
	    def create(self, request, *args, **kwargs):
	        serializer = self.get_serializer(data=request.data)
	        serializer.is_valid(raise_exception=True)
	        user = self.perform_create(serializer)
	
	        re_dict = serializer.data
	
	        # 移除 token
	        re_dict.pop('token', None)
	        # 移除 name
	        re_dict.pop('name', None)
	
	        headers = self.get_success_headers(serializer.data)
	        return Response(re_dict, status=status.HTTP_201_CREATED, headers=headers)
	
	    def perform_create(self, serializer):
	        return serializer.save()

这样子就可以完成短信注册的功能。当然还有写上路由,因为是我视图集的路由我就不具体展示的,怎么写路由网上的教程很多

posted @ 2024-05-30 16:36  shhuang  阅读(18)  评论(0)    收藏  举报