【Django开发】django美多商城项目完整开发4.0第4篇:用户部分,使用Celery完成发送短信【附代码文档】

65 阅读1分钟

教程总体简介:美多商城、商业模式介绍、开发流程、需求分析、项目架构、创建工程、1. 在git平台创建工程、收货地址、省市区地址查询、使用缓存、用户地址管理、用户地址管理代码、用户部分、商品部分、数据库表设计、FastDFS分布式文件系统、Docker使用、Docker简介、安装与操作、使用Docker安装FastDFS、FastDFS客户端与自定义文件存储系统、CKEditor富文本编辑器、添加测试数据、页面静态化、定时任务、静态化首页的手动脚本、商品详情页、用户浏览历史记录、商品列表页、商品搜索、项目准备、配置、用户模型类、注册、购物车数据存储设计、添加到购物车、购物车部分、查询购物车数据、修改购物车数据、删除购物车数据、购物车全选、登录合并购物车、订单数据库设计、订单结算、订单部分、保存订单、下单成功页面、发起支付、保存支付结果、Xadmin、用户权限控制、数据库读写分离、MySQL主从同步、配置Django实现数据库读写分离、部署、图片验证码、短信验证码、跨域CORS、使用Celery完成发送短信、判断帐号是否存在、JWT、什么是JWT、Django REST framework JWT、登录、绑定用户身份接口、用户中心个人信息、邮件与验证、使用Django发送邮件、保存邮箱并发送验证邮件、验证邮箱链接

juejin.cn/post/751686…

juejin.cn/post/752192…

juejin.cn/post/751004…


全套教程部分目录:

用户部分

使用Celery完成发送短信

meiduo/meiduo_mall下创建celery_tasks用于保存celery异步任务。

在celery_tasks目录下创建config.py文件,用于保存celery的配置信息

broker_url = "redis://127.0.0.1/14"

在celery_tasks目录下创建main.py文件,用于作为celery的启动文件

from celery import Celery

  
  
# 为celery使用django配置文件进行设置
  
  
import os
if not os.getenv('DJANGO_SETTINGS_MODULE'):
    os.environ['DJANGO_SETTINGS_MODULE'] = 'meiduo_mall.settings.dev'

  
  
# 创建celery应用
  
  
app = Celery('meiduo')

  
  
# 导入celery配置
  
  
app.config_from_object('celery_tasks.config')

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

在celery_tasks目录下创建sms目录,用于放置发送短信的异步任务相关代码。

将提供的发送短信的云通讯SDK放到celery_tasks/sms/目录下。

在celery_tasks/sms/目录下创建tasks.py文件,用于保存发送短信的异步任务

import logging

from celery_tasks.main import app
from .yuntongxun.sms import CCP

logger = logging.getLogger("django")

  
  
# 验证码短信模板
  
  
SMS_CODE_TEMP_ID = 1

@app.task(name='send_sms_code')
def send_sms_code(mobile, code, expires):
    """
    发送短信验证码
    :param mobile: 手机号
    :param code: 验证码
    :param expires: 有效期
    :return: None
    """

    try:
        ccp = CCP()
        result = ccp.send_template_sms(mobile, [code, expires], SMS_CODE_TEMP_ID)
    except Exception as e:
        logger.error("发送验证码短信[异常][ mobile: %s, message: %s ]" % (mobile, e))
    else:
        if result == 0:
            logger.info("发送验证码短信[正常][ mobile: %s ]" % mobile)
        else:
            logger.warning("发送验证码短信[失败][ mobile: %s ]" % mobile)

在verifications/views.py中改写SMSCodeView视图,使用celery异步任务发送短信

from celery_tasks.sms import tasks as sms_tasks

class SMSCodeView(GenericAPIView):
    ...
        # 发送短信验证码
        sms_code_expires = str(constants.SMS_CODE_REDIS_EXPIRES // 60)
        sms_tasks.send_sms_code.delay(mobile, sms_code, sms_code_expires)

        return Response({"message": "OK"})

判断帐号是否存在

1. 判断用户名是否存在

后端接口设计:

请求方式: GET usernames/(?P<username>\w{5,20})/count/

请求参数: 路径参数

参数类型是否必传说明
usernamestr用户名

返回数据: JSON

{
    "username": "itcast",
    "count": "1"
}
返回值类型是否必须说明
usernamestr用户名
countint数量
后端实现

在users/views.py中定义视图

  
  
# url(r'^usernames/(?P<username>\w{5,20})/count/$', views.UsernameCountView.as_view()), 
  
  
class UsernameCountView(APIView):
    """
    用户名数量
    """
    def get(self, request, username):
        """
        获取指定用户名数量
        """
        count = User.objects.filter(username=username).count()

        data = {
            'username': username,
            'count': count
        }

        return Response(data)
前端实现

在js/register.js中修改

// 检查用户名
    check_username: function (){
            var len = this.username.length;
            if(len<5||len>20) {
                this.error_name_message = '请输入5-20个字符的用户名';
                this.error_name = true;
            } else {
                this.error_name = false;
            }
            // 检查重名
            if (this.error_name == false) {
                axios.get(this.host + '/usernames/' + this.username + '/count/', {
                        responseType: 'json'
                    })
                    .then(response => {
                        if (response.data.count > 0) {
                            this.error_name_message = '用户名已存在';
                            this.error_name = true;
                        } else {
                            this.error_name = false;
                        }
                    })
                    .catch(error => {
                        console.log(error.response.data);
                    })
            }
        },

2. 判断手机号是否存在:

后端接口设计:

请求方式: GET mobiles/(?P<mobile>1[3-9]\d{9})/count

请求参数: 路径参数

参数类型是否必须说明
mobilestr手机号

返回数据: JSON

{
    "mobile": "18512345678",
    "count": 0
}
返回值类型是否必须说明
mobilestr手机号
countint数量
后端实现

在users/views.py中定义视图

  
  
# url(r'^mobiles/(?P<mobile>1[3-9]\d{9})/count/$', views.MobileCountView.as_view()),
  
  
class MobileCountView(APIView):
    """
    手机号数量
    """
    def get(self, request, mobile):
        """
        获取指定手机号数量
        """
        count = User.objects.filter(mobile=mobile).count()

        data = {
            'mobile': mobile,
            'count': count
        }

        return Response(data)
前端实现

在js/register.js中修改

// 检查手机号
    check_phone: function (){
            var re = /^1[345789]\d{9}$/;
            if(re.test(this.mobile)) {
                this.error_phone = false;
            } else {
                this.error_phone_message = '您输入的手机号格式不正确';
                this.error_phone = true;
            }
            if (this.error_phone == false) {
                axios.get(this.host + '/mobiles/'+ this.mobile + '/count/', {
                        responseType: 'json'
                    })
                    .then(response => {
                        if (response.data.count > 0) {
                            this.error_phone_message = '手机号已存在';
                            this.error_phone = true;
                        } else {
                            this.error_phone = false;
                        }
                    })
                    .catch(error => {
                        console.log(error.response.data);
                    })
            }
        },

注册

1. 后端接口设计:

请求方式: POST /users/

请求参数: JSON 或 表单

参数名类型是否必须说明
usernamestr用户名
passwordstr密码
password2str确认密码
sms_codestr短信验证码
mobilestr手机号
allowstr是否同意用户协议

返回数据: JSON

{
    "id": 9,
    "username": "python8",
    "mobile": "18512345678",
}

|返回值|类型|是否必须|说明| |---|