访问方式 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
未完待续