【DJango项目】2.短信验证码 后端逻辑代码实现 celery异步 跨域问题解决

访问方式 GET /sms_codes/{mobile}/?imange_code_id=xxx& text=xxx

返回数据: message str OK发送成功 

 

序列化器 

class CheckImageCodeSerializer(serializers.Serializer):
    """
    图片验证码校验序列化器
    """
    # 从页面获取 验证码id号
    image_code_id = serializers.UUIDField()
    # 从页面获取 验证码
    text = serializers.CharField(min_length=4, max_length=4)

    def validate(self, attrs):
        """
        校验图片验证码用户是否正确
        :param attrs:
        :return:
        """
        image_code_id = attrs["image_code_id"]
        text = attrs["text"]

        # 查询redis数据库 获取真实的验证码
        redis_conn = get_redis_connection("verify_codes")
        real_image_code = redis_conn.get("img_%s" % image_code_id)

        if real_image_code is None:
            # 过期或者不存在
            raise serializers.ValidationError('无效的图片验证码')

        # 删除redis中的图片验证码 防止用户对同一个用户多次请求验证
        # 如果删除错误就跳过 如果不跳过就会抛异常  下面都不会执行
        try:
            redis_conn.delete('img_%s' % image_code_id)
        except RedisError as e:
            logger.error(e)

        # 对比
        real_image_code = real_image_code.decode()
        if real_image_code.lower() != text.lower():
            raise serializers.ValidationError("图片验证码错误")

        # redis中发送短信验证码的标志 send_flag_<mobile> :1,由redis维护60s
        mobile = self.context['view'].kwargs['mobile']
        send_flag = redis_conn.get("send_flag_%s" % mobile)
        if send_flag:
            raise serializers.ValidationError("发送短信过于频繁")

        return attrs

视图

class SMSCodeView(GenericAPIView):
    serializer_class = serializers.CheckImageCodeSerializer

    def get(self, request, mobile):
        # 校验图片验证码和发送短信的频次
        # mobile 被放到类视图对象当中 属性kwargs
        serializer = self.get_serializer(data=request.query_params)
        serializer.is_valid(raise_exception=True)

        # 校验通过 生成短息验证码
        sms_code = '%06d' % random.randint(0, 999999)

        # 保存验证码及发送记录
        redis_conn = get_redis_connection('verify_codes')

        # redis_conn.setex("sms_%s" % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code)
        # redis_conn.setex('send_flag_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL, 1)

        # 使用redis pipeline管道 一次执行多个命令
        pl = redis_conn.pipline()
        pl.setex("sms_%s" % mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code)
        pl.setex('send_flag_%s' % mobile, constants.SEND_SMS_CODE_INTERVAL, 1)
        # 让管道执行命令
        pl.execute()

        # 发送短信
        ccp = CCP()
        time = constants.SMS_CODE_REDIS_EXPIRES / 60
        ccp.send_template_sms(mobile, [sms_code, time], constants.SMS_CODE_TEMP_ID)

        # 返回
        return Response({'message': 'OK'}, status=200)

 

Django 异步发起者   ----------------> Redis broker 任务列表  ---------------->  Celey 异步发送短信

                                        ---------> backend(保存异步结果) <-----------

 

目录: celery_task 

      ---sms   # 任务目录

        ---tasks.py    # 执行任务函数

      __init__.py

      config.py  # 配置文件 

      main.py   # 执行文件

安装 : pip  install -U Celery 

config.py

broker_url = "redis://127.0.0.1/14"
result_backend = "redis://127.0.0.1/15"

main.py

from celery import Celery

celery_app = Celery("meiduo")

# 导入配置文件
celery_app.config_from_object("celery_task.config")

# 自动注册celery任务
celery_app.autodiscover_tasks(['celery_tasks.sms'])

 

 

解决跨域问题

pip install django-cors-headers 

 

MIDDLEWARE = [
'corsheaders.middleware.CoresMiddleware',
]

INSTALLED_APPS = [
   'corsheaders',
]

白名单配置 :
# CORS
CORS_ORIGIN_WHITELIST = (
    'http://127.0.0.1:8080',
    'http://localhost:8080',
    'www.meiduo.site:8080'
)
CORS_ALLOW_CREDENTIALS = True  # 允许携带cookie

参考 https://blog.csdn.net/qq_42799459/article/details/90611119

未完待续 

 

posted @ 2020-02-24 20:51  阿里云的奥斯卡  阅读(249)  评论(1编辑  收藏  举报