小米商城项目_注册

1. 前端

1.1 模型类

from django.db import models

# Create your models here.

# 用户模型
class User(models.Model):
    username = models.CharField(max_length=32,verbose_name='用户名',unique=True)
    password = models.CharField(max_length=32,verbose_name='密码')
    mobile = models.CharField(max_length=16,verbose_name='手机号')
    class Meta:
        verbose_name = '用户表'
        verbose_name_plural = verbose_name
    def __str__(self):
        return '%s (%s)' % (self.username,self.mobile)

1.2视图


import redis,random,re
from django.http import HttpResponse
from rest_framework.response import Response
from rest_framework.views import APIView
from user.models import User
from captcha.image import ImageCaptcha
from django.shortcuts import render

# Create your views here.

# 定义检查用户名的类视图
class CheckUserNameView(APIView):
    def get(self,request,username):
        if not username:
            return Response({
                'code':400,
                'msg':'用户名错误'
            })
        # 检测用户名长度
        if not (6 <= len(username) <= 32):
            return Response({
                'code':400,
                'msg':'用户长度不符合'
            })
        # 程序走到这一步 代表用户名长度符合
        # 检测用户名唯一性
        # 查询数据库有没有符合username的这条数据
        user_count = User.objects.filter(username=username).count()
        if user_count:
            # 查询出的用户条数不为0
            return Response({
                'code':400,
                'msg':'用户名已存在'
            })
        return Response({
            'code':200,
            'msg':'用户名可用'
        })

# 校验手机号类视图
class CheckMobileView(APIView):
    def get(self,request,mobile):
        rule = r'^1[3-9][0-9]{9}$'  # 定义手机号的正则

        rs = re.findall(rule,mobile) # 返回的是列表,如果匹配不到 返回的是空列表 如果匹配到 返回匹配的数据组成的列表
        if not rs:
            return Response({
                'code':400,
                'msg':'手机号格式不匹配'
            })

        # 程序走到这一步 代表手机号格式没有问题
        # 进行判断数据库有没有这个数据
        mobile_count = User.objects.filter(mobile=mobile).count()
        if mobile_count:
            return Response({
                'code':400,
                'msg':'手机号已存在'
            })
        return Response({
            'code':200,
            'msg':'手机号可用'
        })
# 校验密码
class CheckpwdView(APIView):
    def post(self,request):
        pwd = request.data.get('pwd') # 接收传过来的密码

        # 校验
        if not (6 <= len(pwd) <= 32):
            return Response({
                'code':400,
                'msg':'密码长度不可用'
            })
        return Response({
            'code':200,
            'msg':'密码可用'
        })

# 检测二次输入密码
class CheckpwdReView(APIView):
    def post(self,request):
        pwd = request.data.get('pwd')# 一次
        pwd_re = request.data.get('pwd_re')# 二次
        if pwd != pwd_re:
            return Response({
                'code':400,
                'msg':'两次输入密码不一致'
            })
        return Response({
            'code':200,
            'msg':'密码一致'
        })

# 生成验证码
class VerImageView(APIView):
    def get(self,request,uuid):
        # 1.生成随机验证码
        code = str(random.randint(1000,9999))


        img = ImageCaptcha() # 实例化验证码的类
        img_pic = img.generate(code) # 生成图片验证码
        print('生成的图片是',img_pic)# 返回值是IO字节流

        # 把验证码存到redis
        import redis
        r = redis.Redis(host='127.0.0.1',port=6379,password='123456')
        r.set(uuid,code,ex=60*5) # 实效时间 5分钟

        print(uuid)
        print(code)
        # return Response(uuid)
        return HttpResponse(img_pic,content_type='image/png')

# 校验认证码的API
class CheckCodeView(APIView):
    def post(self,request):
        code = request.data.get('code') # 用户输入的验证码
        uuid = request.data.get('uuid') # 用户的唯一标志

        # 1.连接数据库,取出uuid 对应的验证码
        r = redis.Redis(
            host='127.0.0.1',port=6379,password='123456'
        )
        sys_code = r.get(uuid)  # 获取到的是字节类型的数据 不能与字符串比较

        # 如果uuid对应的数据为空,说明验证码已过期
        if not sys_code:
            return Response({
                'code':400,
                'msg':'验证码已过期'
            })
        sys_code_str = sys_code.decode() # 获取到数据转换为字符串类型

        # 2.用用户输入的验证码和数据库的验证码作别对
        # 如果不一致,验证码错误
        if sys_code_str != code:
            return Response({
                'code': 400,
                'msg': '验证码不一致'
            })

        # 如果一致说明验证码通过
        return Response({
            'code':200,
            'msg':'验证通过'
        })

# 注册类视图
class RegView(APIView):
    def post(self,request):
        username = request.data.get('username')
        password = request.data.get('password')
        mobile = request.data.get('mobile')
        agree = request.data.get('agree')

        # 判断一下用户是否勾选协议
        if not int(agree): # 转int 是因为 字符串“0” 不能来判断
            return Response({
                'code': 400,
                'msg': '请勾选协议'
            })

        if not username or not password or not mobile:
            return Response({
                'code':400,
                'msg':'参数输入有误'
            })

        # T0D0 校验用户名、密码、手机号

        # 校验完毕写入数据库
        try:
            # 写入数据库的操作
            User.objects.create(
                username=username,
                password=password,
                mobile=mobile
            )
            return Response({
                'code': 200,
                'msg': '注册成功'
            })
        except Exception as e:
            print(e)
            return Response({
                'code': 400,
                'msg': '注册失败'
            })

1.3 路由

from django.urls import path

from user import views

urlpatterns = [
    path('check/username/<str:username>/',views.CheckUserNameView.as_view()), # 检测用户名
    path('check/mobile/<str:mobile>/',views.CheckMobileView.as_view()), # 检测手机号
    path('check/pwd/',views.CheckpwdView.as_view()), # 检验密码
    path('check/pwd_re/',views.CheckpwdReView.as_view()), # 检验二次密码
    path('check/image/<str:uuid>/',views.VerImageView.as_view()), # 生成验证码
    path('check/img/code/',views.CheckCodeView.as_view()), # 校验验证码
    path('reg/',views.RegView.as_view()), # 注册
]

2. 前端

<!--
 * @Description: 用户注册组件
 * @Author: hai-27
 * @Date: 2020-02-19 22:20:35
 * @LastEditors: hai-27
 * @LastEditTime: 2020-03-01 15:34:34
 -->
<template>
  <div id="register">
    <el-dialog title="注册" width="300px" center :visible.sync="isRegister">
      <el-form
          :model="RegisterUser"
          :rules="rules"
          status-icon
          ref="ruleForm"
          class="demo-ruleForm"
      >
        <!-- 用户名 -->
        <el-form-item prop="name">
          <el-input
              prefix-icon="el-icon-user-solid"
              placeholder="请输入账号"
              v-model="RegisterUser.name"
          ></el-input>
        </el-form-item>

        <!-- 密码 -->
        <el-form-item prop="pass">
          <el-input
              prefix-icon="el-icon-view"
              type="password"
              placeholder="请输入密码"
              v-model="RegisterUser.pass"
          ></el-input>
        </el-form-item>
        <!-- 确认密码 -->
        <el-form-item prop="confirmPass">
          <el-input
              prefix-icon="el-icon-view"
              type="password"
              placeholder="请再次输入密码"
              v-model="RegisterUser.confirmPass"
          ></el-input>
        </el-form-item>

        <!-- 输入手机号 -->
        <el-form-item prop="mobile">
          <el-input
              prefix-icon="el-icon-user-solid"
              placeholder="请输入手机号"
              v-model="RegisterUser.mobile"
          ></el-input>
        </el-form-item>

        <!-- 增加的内容 -->
        <el-form-item prop='imageCode'>
          <!-- 图片验证码 -->
          <el-input
              placeholder="输入验证码"
              v-model="RegisterUser.imageCode"
              :style="{width:'60%'}"
          ></el-input>
          <img class='imageCode' :src="iamgeCodeUrl" alt="图形验证码" @click="genImageCode">
        </el-form-item>
        <!-- 是否同意商城协议 -->
        <el-form-item prop='aggreement'>
          <el-checkbox v-model="aggree">
            <label class='aggreement'>同意'商城用户使用协议'</label>
          </el-checkbox>
          <br>
          <span class="error_tip" v-show="flag">请勾选用户协议</span>
        </el-form-item>

        <!-- 点击注册 -->
        <el-form-item>
          <el-button
              size="medium"
              type="primary"
              @click="Register"
              style="width: 100%"
          >注册
          </el-button
          >
        </el-form-item>
      </el-form>
    </el-dialog>
  </div>
</template>


<script>
// 生成uuid
import {v4 as uuid4} from 'uuid'

export default {
  name: "MyRegister",
  props: ["register"],
  data() {
    // 用户名的校验方法
    let validateName = (rule, value, callback) => {
      console.log("校验用户名,规则", rule, "用户名", value, "回调函数", callback)
      // TODO 校验用户名
      // 失败 return callback(new Error("字母开头,长度5-16之间,允许字母数字下划线"));
      // 成功 return callback();
    if (!value){
      return
    }
      this.$axios.get('/user/check/username/'+value+'/')
    .then((result) => {
      if (result.data.code == 200){
        return callback();
      }else{
        return callback(new Error(result.data.msg));
      }
      }).catch((err) => {
      console.log(err)
      console.log('页面报错了')
      });
    };
    // 手机号的校验方法
    let validateMobile = (rule, value, callback) => {
      console.log("校验手机号,规则", rule, "手机号", value, "回调函数", callback)
      // TODO 校验手机号
      // 失败 return callback(new Error("字母开头,长度5-16之间,允许字母数字下划线"));
      // 成功 return callback();
      if (!value){
        return
      }
      this.$axios('/user/check/mobile/' + value+ '/')
      .then((result) => {
        if (result.data.code == 200){
          return callback();
        }else{
          return callback(new Error(result.data.msg));
        }
      }).catch((err) => {
          console.log(err)
      });
    };
    // 密码的校验方法
    let validatePass = (rule, value, callback) => {
      console.log("校验密码,规则", rule, "密码", value, "回调函数", callback)
      // TODO 校验密码
      // 失败 return callback(new Error("字母开头,长度5-16之间,允许字母数字下划线"));
      // 成功 return callback();
      if (!value){
        return
      }
      this.$axios.post('/user/check/pwd/',{'pwd':value})
      .then((result) => {
        if (result.data.code == 200){
          return callback();
        }else{
          return callback(new Error(result.data.msg));
        }
      }).catch((err) => {
        console.log(err)
      });
    };
    // 确认密码的校验方法
    let validateConfirmPass = (rule, value, callback) => {
      console.log("校验确认密码,规则", rule, "二次输入的密码", value, "回调函数", callback)
      // TODO 校验确认密码
      // 失败 return callback(new Error("字母开头,长度5-16之间,允许字母数字下划线"));
      // 成功 return callback();
      this.$axios.post('/user/check/pwd_re/',{
        'pwd':this.RegisterUser.pass,
        'pwd_re':value
      })
      .then((result) => {
        if (result.data.code == 200){
          return callback();
        }else{
          return callback(new Error(result.data.msg));
        }
        
      }).catch((err) => {
        console.log(err)
      });
    };
    // 校验图片验证码
    let validateImageCode = (rule, value, callback) => {
      console.log("校验验证码,规则", rule, "二验证码", value, "回调函数", callback)
      // TODO 校验验证码
      // 失败 return callback(new Error("字母开头,长度5-16之间,允许字母数字下划线"));
      // 成功 return callback();
      this.$axios.post('/user/check/img/code/',{
        'uuid':this.imageCodeID,
        'code':value
        })
        .then((result) => {
          if (result.data.code == 200){
            return callback();
          }else{
            return callback(new Error(result.data.msg));
          }
        }).catch((err) => {
          console.log(err)
        });

      
    };
    return {
      imageCodeID: "",//即生成的uuid
      iamgeCodeUrl: "", //图形验证码的地址
      isRegister: false, // 控制注册组件是否显示
      aggree: false,//是否同意协议
      flag: false, //控制勾选协议的提示
      // 返回的是注册用户信息
      RegisterUser: {
        name: "",
        pass: "",
        confirmPass: "",
        mobile: "",
        imageCode: "",//用户输入的图片验证码
      },
      // 用户信息校验规则,validator(校验方法),trigger(触发方式),blur为在组件 Input 失去焦点时触发
      rules: {
        // 这里的属性值,是prop的值
        name: [{validator: validateName, trigger: "blur"}],
        pass: [{validator: validatePass, trigger: "blur"}],
        confirmPass: [{validator: validateConfirmPass, trigger: "blur"}],
        mobile: [{validator: validateMobile, trigger: "blur"}],
        imageCode: [{validator: validateImageCode, trigger: "blur"}],
      },
    };
  },

  watch: {
    // 监听父组件传过来的register变量,设置this.isRegister的值
    register: function (val) {
      if (val) {
        this.isRegister = val;
      }
    },
    // 监听this.isRegister变量的值,更新父组件register变量的值
    isRegister: function (val) {
      if (!val) {
        this.$refs["ruleForm"].resetFields();
        this.$emit("fromChild", val);
      }
    },
  },
  mounted() {
    // DOM节点刚刚完成挂载,生成默认的图形验证码
    this.genImageCode()
  },

  methods: {

    // 生成图片验证码地址
    genImageCode() {
      // 生成一个uuid
      this.imageCodeID = uuid4() // UUID 理解成 随机字符串 用来确认你是谁
      // 生成一个图片验证码地址
      this.iamgeCodeUrl = "/user/check/image/" + this.imageCodeID + "/"
    },

    // 用户注册
    Register() {
      // 是否同意用户协议
      if (!this.aggree) {
        this.flag = true
        return
      }
      // 已勾选,则不显示提示信息
      this.flag = false
      // 通过element自定义表单校验规则,校验用户输入的用户信息
      this.$refs["ruleForm"].validate((valid) => {
        if (valid) {
          // TODO 注册用户
          this.$axios.post('/user/reg/',{
            username:this.RegisterUser.name,
            password:this.RegisterUser.pass,
            mobile:this.RegisterUser.mobile,
            agree:this.aggree
          })
          .then((result) => {
            if(result.data.code == 200){
              // 清空注册输入的内容
              this.RegisterUser.name = '',
              this.RegisterUser.pass = '',
              this.RegisterUser.mobile = '',
              this.RegisterUser.confirmPass = '',
              this.RegisterUser.imageCode = '',
              this.aggree = false

              // 关闭注册弹窗
              this.isRegister = false
              // alert('注册成功')
              this.notifySucceed(result.data.msg)
            }else{
            this.notifySucceed(result.data.msg)
            }
          }).catch((err) => {
            console.log(err)
            alert('页面报错了')
          });
        } else {
          return false;
        }
      });
    },
  },
};
</script>


<style>
.imageCode {
  /* padding-top:2%; */
  margin-bottom: -12px;
  width: 95px;
  height: 35px;
}

.aggreement {
  font-size: 10px;
  color: blue;
}

.error_tip {
  font-size: 3px;
  color: red;
}
</style>

3. 效果图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值