zoukankan      html  css  js  c++  java
  • DAY 82 vue06

    1 前端配置请求后端的地址
    2 meida的配置
    -media_url
    3 前端登录功能
    -判断用户名密码是否为空,message的提示
       -发送axios请求(post)
    4 前端存储(三个位置)

    5 前端用户名的显示与不显示

    6 发送短信(腾讯云)
    -api和sdk
       -发送短信的2.0的sdk
       -封装了一层(单独做成一个模块,以后可以顺利的移到任何其他项目中)
    7 校验手机号是否存在的接口

    8 限制短信发送频率的频率类

    1 手机号登录接口

    1 只需要手机号和验证码,post

    views.py

        @action(methods=['POST'], detail=False)
       def login_phone(self, request, *args, **kwargs):

           # 序列化类
           ser = UserPhoneModelSerializer(data=request.data)
           ser.is_valid(raise_exception=True)
           token = ser.context['token']
           user = ser.context['user']
           return APIResponse(token=token, username=user.username, id=user.id)

     

    serializer.py

    from django.core.cache import cache
    from django.conf import settings


    class UserPhoneModelSerializer(serializers.ModelSerializer):
       # 需要重写code
       code = serializers.CharField()
       mobile = serializers.CharField(max_length=11)

       class Meta:
           model = models.User
           fields = ['mobile', 'code']

       # 写全局钩子(校验手机号和验证码是否正确,登录成功,签发token)
       def validate(self, attrs):

           mobile = attrs.get('mobile')
           code = attrs.get('code')
           # 从缓存中取出这个手机号对应的验证码
           cache_code = cache.get(settings.SMS_PHONE_CACHE % mobile)
           if cache_code and cache_code == code:
               # 可以登录,根据手机号,查到用户,给这个用户签发token
               user = models.User.objects.get(mobile=mobile)
               # 签发token
               payload = jwt_payload_handler(user)
               token = jwt_encode_handler(payload)
               self.context['token'] = token
               self.context['user'] = user
               return attrs

           else:
               raise ValidationError('验证码错误')

     

    2 前端获取验证码,手机号登录,前端注册功能

    Register.vue

    <template>
       <div class="register">
           <div class="box">
               <i class="el-icon-close" @click="close_register"></i>
               <div class="content">
                   <div class="nav">
                       <span class="active">新用户注册</span>
                   </div>
                   <el-form>
                       <el-input
                               placeholder="手机号"
                               prefix-icon="el-icon-phone-outline"
                               v-model="mobile"
                               clearable
                               @blur="check_mobile">
                       </el-input>
                       <el-input
                               placeholder="密码"
                               prefix-icon="el-icon-key"
                               v-model="password"
                               clearable
                               show-password>
                       </el-input>
                       <el-input
                               placeholder="验证码"
                               prefix-icon="el-icon-chat-line-round"
                               v-model="sms"
                               clearable>
                           <template slot="append">
                               <span class="sms" @click="send_sms">{{ sms_interval }}</span>
                           </template>
                       </el-input>
                       <el-button type="primary" @click="register">注册</el-button>
                   </el-form>
                   <div class="foot">
                       <span @click="go_login">立即登录</span>
                   </div>
               </div>
           </div>
       </div>
    </template>

    <script>
       export default {
           name: "Register",
           data() {
               return {
                   mobile: '',
                   password: '',
                   sms: '',
                   sms_interval: '获取验证码',
                   is_send: false,
              }
          },
           methods: {
               close_register() {
                   this.$emit('close', false)
              },
               go_login() {
                   this.$emit('go')
              },
               check_mobile() {
                   if (!this.mobile) return;
                   if (!this.mobile.match(/^1[3-9][0-9]{9}$/)) {
                       this.$message({
                           message: '手机号有误',
                           type: 'warning',
                           duration: 1000,
                           onClose: () => {
                               this.mobile = '';
                          }
                      });
                       return false;
                  }
                   this.is_send = true;


                   //校验手机号如果存在就不用注册,直接去登录
                   this.$http.get(this.$BASE_URL + 'user/check_phone/', {params: {phone: this.mobile}}).then(res => {
                       console.log(res.data)
                       if (res.data.code == 100) {
                           this.is_send = false;

                           this.$message({
                               message: '该账号已经存在,请直接去登录',
                               type: 'success',
                          })
                           this.is_send = true;
                      } else {
                           this.is_send = true;
                           this.$message({
                               message: '可以正常注册',
                               type: 'warning',
                          })
                      }
                  })
              },
               register() {
                   if(!(this.mobile &&this.sms && this.password)){
                       this.$message({
                               message: '手机号,验证码,密码不能为空',
                               type: 'error',
                          })
                       return
                  }
                   this.$http.post(this.$BASE_URL + 'user/register/', {
                       mobile: this.mobile,
                       code: this.sms,
                       password: this.password
                  }).then(res => {
                       if (res.data.code == 100) {
                           this.$message({
                               message: '注册成功,请去登录',
                               type: 'success',
                          })
                           //关掉注册框,打开登录框
                           this.go_login()
                      } else {
                           this.$message({
                               message: '注册失败,请稍后再试',
                               type: 'error',
                          })
                      }
                  })

              },
               send_sms() {
                   if (!this.is_send) return;
                   this.is_send = false;
                   let sms_interval_time = 60;
                   this.sms_interval = "发送中...";
                   let timer = setInterval(() => {
                       if (sms_interval_time <= 1) {
                           clearInterval(timer);
                           this.sms_interval = "获取验证码";
                           this.is_send = true; // 重新回复点击发送功能的条件
                      } else {
                           sms_interval_time -= 1;
                           this.sms_interval = `${sms_interval_time}秒后再发`;
                      }
                  }, 1000);

                   this.$http.get(this.$BASE_URL + 'user/send_sms/?phone=' + this.mobile).then(res => {
                       console.log(res.data)
                       if (res.data.code == 100) {
                           this.$message({
                               message: '短信发送成功',
                               type: 'success',
                          })
                      } else {
                           this.$message({
                               message: '短信发送失败,请稍后再试。。。',
                               type: 'error',
                          })
                      }
                  })


              }
          }
      }
    </script>

    <style scoped>
      .register {
            100vw;
           height: 100vh;
           position: fixed;
           top: 0;
           left: 0;
           z-index: 10;
           background-color: rgba(0, 0, 0, 0.3);
      }

      .box {
            400px;
           height: 480px;
           background-color: white;
           border-radius: 10px;
           position: relative;
           top: calc(50vh - 240px);
           left: calc(50vw - 200px);
      }

      .el-icon-close {
           position: absolute;
           font-weight: bold;
           font-size: 20px;
           top: 10px;
           right: 10px;
           cursor: pointer;
      }

      .el-icon-close:hover {
           color: darkred;
      }

      .content {
           position: absolute;
           top: 40px;
            280px;
           left: 60px;
      }

      .nav {
           font-size: 20px;
           height: 38px;
           border-bottom: 2px solid darkgrey;
      }

      .nav > span {
           margin-left: 90px;
           color: darkgrey;
           user-select: none;
           cursor: pointer;
           padding-bottom: 10px;
           border-bottom: 2px solid darkgrey;
      }

      .nav > span.active {
           color: black;
           border-bottom: 3px solid black;
           padding-bottom: 9px;
      }

      .el-input, .el-button {
           margin-top: 40px;
      }

      .el-button {
            100%;
           font-size: 18px;
      }

      .foot > span {
           float: right;
           margin-top: 20px;
           color: orange;
           cursor: pointer;
      }

      .sms {
           color: orange;
           cursor: pointer;
           display: inline-block;
            70px;
           text-align: center;
           user-select: none;
      }
    </style>

    Login.vue

    <template>
       <div class="login">
           <div class="box">
               <i class="el-icon-close" @click="close_login"></i>
               <div class="content">
                   <div class="nav">
                       <span :class="{active: login_method === 'is_pwd'}"
                             @click="change_login_method('is_pwd')">密码登录</span>
                       <span :class="{active: login_method === 'is_sms'}"
                             @click="change_login_method('is_sms')">短信登录</span>
                   </div>
                   <el-form v-if="login_method === 'is_pwd'">
                       <el-input
                               placeholder="用户名/手机号/邮箱"
                               prefix-icon="el-icon-user"
                               v-model="username"
                               clearable>
                       </el-input>
                       <el-input
                               placeholder="密码"
                               prefix-icon="el-icon-key"
                               v-model="password"
                               clearable
                               show-password>
                       </el-input>
                       <el-button type="primary" @click="pwd_login">登录</el-button>
                   </el-form>
                   <el-form v-if="login_method === 'is_sms'">
                       <el-input
                               placeholder="手机号"
                               prefix-icon="el-icon-phone-outline"
                               v-model="mobile"
                               clearable
                               @blur="check_mobile">
                       </el-input>
                       <el-input
                               placeholder="验证码"
                               prefix-icon="el-icon-chat-line-round"
                               v-model="sms"
                               clearable>
                           <template slot="append">
                               <span class="sms" @click="send_sms">{{ sms_interval }}</span>
                           </template>
                       </el-input>
                       <el-button type="primary" @click="phone_login">登录</el-button>
                   </el-form>
                   <div class="foot">
                       <span @click="go_register">立即注册</span>
                   </div>
               </div>
           </div>
       </div>
    </template>

    <script>
       export default {
           name: "Login",
           data() {
               return {
                   username: '',
                   password: '',
                   mobile: '',
                   sms: '',
                   login_method: 'is_pwd',
                   sms_interval: '获取验证码',
                   is_send: false,
              }
          },
           methods: {
               close_login() {
                   this.$emit('close')
              },
               go_register() {
                   this.$emit('go')
              },

               //密码登录方法
               pwd_login() {
                   if (!(this.username && this.password)) {
                       //用户名或密文为空
                       this.$message({
                           message: '用户名或密码不能为空',
                           type: 'warning'
                      });

                  } else {
                       //发送axios请求
                       this.$http.post(this.$BASE_URL + 'user/login/', {
                           username: this.username,
                           password: this.password
                      }).then(res => {
                           console.log(res)
                           if (res.data.code == 100) {
                               //登录成功

                               //1 存储返回的token,username(可以存的地方有三个)
                               //咱们放到cookie中(放到cookie中)
                               this.$cookies.set('token', res.data.token, '7d')
                               this.$cookies.set('username', res.data.username, '7d')
                               // sessionStorage.setItem()
                               // sessionStorage.getItem()
                               // localStorage.setItem()
                               // localStorage.getItem()
                               //2 销毁框
                               this.close_login()


                          } else {
                               this.$message({
                                   message: res.data.msg,
                                   type: 'warning'
                              });
                          }
                      })
                  }

              },

               //手机号登录
               phone_login() {
                   if (!(this.mobile && this.sms)) {
                       //用户名或密文为空
                       this.$message({
                           message: '手机号或验证码不能为空',
                           type: 'warning'
                      });

                  } else {
                       //发送axios请求
                       this.$http.post(this.$BASE_URL + 'user/login_phone/', {
                           mobile: this.mobile,
                           code: this.sms
                      }).then(res => {
                           console.log(res)
                           if (res.data.code == 100) {
                               //登录成功
                               this.$cookies.set('token', res.data.token, '7d')
                               this.$cookies.set('username', res.data.username, '7d')
                               this.close_login()

                          } else {
                               this.$message({
                                   message: res.data.msg,
                                   type: 'warning'
                              });
                          }
                      })
                  }

              },
               change_login_method(method) {
                   this.login_method = method;
              },
               check_mobile() {
                   if (!this.mobile) return;  //如果手机号没填,这个方法结束了
                   //js的正则   字符串.match('/正则表达式/')
                   if (!this.mobile.match(/^1[3-9][0-9]{9}$/)) {
                       this.$message({
                           message: '手机号有误',
                           type: 'warning',
                           duration: 1000,  //message的显示时间
                           onClose: () => {
                               this.mobile = '';  //把手机号清空
                          },

                      });
                       return false;
                  }

                   //前端输入的手机号是正确手机号,去后端,查看手机号是否存在

                   // this.$http.get(this.$BASE_URL+'user/check_phone/?phone='+this.mobile)
                   this.$http.get(this.$BASE_URL + 'user/check_phone/', {params: {phone: this.mobile}}).then(res => {
                       console.log(res.data)
                       if (res.data.code == 100) {
                           //正常的,可以发送验证码,如果点击发送验证码按钮,就能点击,否则为false,就不能点击
                           this.$message({
                               message: '该手机可以发送验证码',
                               type: 'success',
                          })
                           this.is_send = true;
                      } else {
                           this.is_send = false;
                           this.mobile = ''
                           this.$message({
                               message: res.data.msg,
                               type: 'warning',
                          })
                      }
                  })


              },
               send_sms() {

                   if (!this.is_send) return;
                   this.is_send = false;
                   let sms_interval_time = 60;
                   this.sms_interval = "发送中...";
                   let timer = setInterval(() => {
                       if (sms_interval_time <= 1) {
                           clearInterval(timer);
                           this.sms_interval = "获取验证码";
                           this.is_send = true; // 重新回复点击发送功能的条件
                      } else {
                           sms_interval_time -= 1;
                           this.sms_interval = `${sms_interval_time}秒后再发`;
                      }
                  }, 1000);
                   //向后端发送短信接口发请求,给这个手机号发短信
                   this.$http.get(this.$BASE_URL + 'user/send_sms/?phone=' + this.mobile).then(res => {
                       console.log(res.data)
                       if (res.data.code == 100) {
                           this.$message({
                               message: '短信发送成功',
                               type: 'success',
                          })
                      } else {
                           this.$message({
                               message: '短信发送失败,请稍后再试。。。',
                               type: 'error',
                          })
                      }
                  })
              }
          }
      }
    </script>

    <style scoped>
      .login {
            100vw;
           height: 100vh;
           position: fixed;
           top: 0;
           left: 0;
           z-index: 10;
           background-color: rgba(0, 0, 0, 0.3);
      }

      .box {
            400px;
           height: 420px;
           background-color: white;
           border-radius: 10px;
           position: relative;
           top: calc(50vh - 210px);
           left: calc(50vw - 200px);
      }

      .el-icon-close {
           position: absolute;
           font-weight: bold;
           font-size: 20px;
           top: 10px;
           right: 10px;
           cursor: pointer;
      }

      .el-icon-close:hover {
           color: darkred;
      }

      .content {
           position: absolute;
           top: 40px;
            280px;
           left: 60px;
      }

      .nav {
           font-size: 20px;
           height: 38px;
           border-bottom: 2px solid darkgrey;
      }

      .nav > span {
           margin: 0 20px 0 35px;
           color: darkgrey;
           user-select: none;
           cursor: pointer;
           padding-bottom: 10px;
           border-bottom: 2px solid darkgrey;
      }

      .nav > span.active {
           color: black;
           border-bottom: 3px solid black;
           padding-bottom: 9px;
      }

      .el-input, .el-button {
           margin-top: 40px;
      }

      .el-button {
            100%;
           font-size: 18px;
      }

      .foot > span {
           float: right;
           margin-top: 20px;
           color: orange;
           cursor: pointer;
      }

      .sms {
           color: orange;
           cursor: pointer;
           display: inline-block;
            70px;
           text-align: center;
           user-select: none;
      }
    </style>

     

    3 后端注册接口

    1 前端传入是不带用户名的,我们可以自动生成一个用户名,或者使用手机号作为用户(咱们)
    2 邮箱也没传入(邮箱可以为空)
    3 前端出入
    -手机号
       -密码
       -code(表中没有)
    4 post请求

    views.py

        @action(methods=['POST'], detail=False)
       def register(self, request, *args, **kwargs):
           # 序列化类
           ser = UserRegisterModelSerializer(data=request.data)
           ser.is_valid(raise_exception=True)
           ser.save() # 新增会触发,serializer的create方法,重写create方法
           return APIResponse(code=100,msg='注册成功')

    serializer.py

    class UserRegisterModelSerializer(serializers.ModelSerializer):
    code = serializers.CharField(write_only=True)

    class Meta:
    model = models.User
    fields = ['mobile', 'code', 'password']

    # # code这个字段只用来写
    # extra_kwargs = {
    # 'code': {'write_only': True}
    # }

    # 可给手机号和password加局部校验钩子
    def validate_mobile(self, data):
    import re
    if re.match('^1[3-9][0-9]{9}$', data):
    return data
    else:
    raise ValidationError('手机号不合法')

    def validate(self, attrs):
    mobile = attrs.get('mobile')
    code = attrs.get('code')
    # 校验code是否是我们给的
    # 从缓存中取出这个手机号对应的验证码
    cache_code = cache.get(settings.SMS_PHONE_CACHE % mobile)
    if cache_code and cache_code == code:
    # 可以注册
    # 如何注册?需要重写create,由于密码是密文,需要重写,使用create_user来创建用户
    # 把code剔除
    attrs.pop('code')
    # 加入username
    attrs['username'] = mobile
    return attrs
    else:
    raise ValidationError('验证码错误')

    def create(self, validated_data):
    # validated_data:username,password,mobile (email,icon都可以为空)
    user = models.User.objects.create_user(**validated_data)
    return user

     

    ##

    5 redis介绍安装

    1 redis数据库,非关系型(redis:内存数据库,所有数据放在内存中,mongodb:数据放在硬盘上,es:放在硬盘上)
    2 关系型:mysql,db2,oracle,posgresql,sqlserver,达梦(国产数据),sql都是通用的,表和表之间的关联关系,事务的支持比较好,锁机制


    3 redis是一个key-value存储系统。
    -key-value存储
    -支持5大数据类型:字符串,列表,字典(hash),集合,有序集合
    -6.0之前单线程,单进程的
    -redis是单线程为什么这么快?
    -全内存操作
    -基于io多路复用的模型
    -没有多线程多进程的切换
    -性能高,单机qps高达10w,实际生产环境实际6w
    -可以持久化
    -c语言写的
    4 Memcached:内存数据库,key-value存储,支持的数据类型少,只有str类型,没有持久化,断电消失

    5 redis不支持windows,io多路复用的模型,在linux使用的是epoll,在windwos上没有epoll,于是有一些第三方,基于源码改动了一些,让他可以在windows上执行(最新版只到3.x)
    6 windows的下载地址
    -https://github.com/microsoftarchive/redis/releases
    7 windows安装
    -一路下一步:添加到环境变量,端口号是6379,使用的最大内存,不限制

    8 装完之后,就会有个redis服务
    -通过启动服务,停止服务来运行停止redis
    9 命令方式启动和停止
    -启动
    redis-server 配置文件路径 # 使用配置文件启动
    redis-server # 不使用配置文件启动
    -客户端连接
    redis-cli # 连接上本地 127.0.0.1 6379
    redis-cli -h 127.0.0.1 -p 6378
    在客户端:shutdown
    在客户端敲:ping 回一个pone
    10 redis的客户端很多
    -redis-desktop-manager
    -qt:平台,专门用来写图形化介模
    -pyqt:用python代码在qt平台写图形化界面

    11 在客户端写
    set name lqz
    get name

     

    6 python操作redis之普通连接和连接池

    # pip install redis

    # redis之普通连接
    # from redis import Redis
    # conn = Redis(host='127.0.0.1',port=6379) # 什么都不写,连的就是本地的6379
    # # 获取name这个key对应的值
    # res=conn.get('name')
    # print(res)
    # conn.close()

    # redis连接之连接池

    import redis
    # 先定义一个池子,池子大小指定
    # 这个pool必须做成一个单例(这句话只写一次)
    #
    # pool = redis.ConnectionPool(max_connections=10)

    # 当该py文件以脚本运行,其中包的导入不能使用相对导入
    # 如果是以模块形式导入使用,这个模块内可以使用相对导入

    from redis_pool import POOL #天然的单例,不管导入多少次,只会实例化一次
    # 建立连接,从池子中获取一个连接
    conn=redis.Redis(connection_pool=POOL)

    res=conn.get('name')
    print(res)

     

    7 字符串操作


    from redis import Redis
    conn = Redis(host='127.0.0.1',port=6379) # 什么都不写,连的就是本地的6379

    # 1 设置值
    # conn.set('age',16)
    # conn.set('name','刘清政')
    # conn.set('hobby','篮球')
    # conn.set('hobby','篮球',ex=3,nx=True)
    # conn.set('hobby','足球',ex=3,nx=True)
    # conn.set('hobby','足球',xx=True)
    # conn.set('hobby1','足球',xx=True)
    '''
    ex,过期时间(秒)
    px,过期时间(毫秒)
    nx,如果设置为True,则只有name不存在时,当前set操作才执行,值存在,就修改不了,执行没效果
    xx,如果设置为True,则只有name存在时,当前set操作才执行,值存在才能修改,值不存在,不会设置新值
    '''

    # 2 取值
    # print(str(conn.get('name'),encoding='utf-8')) #取出来的值是bytes格式,以utf-8形式


    # 3 setnx

    # 4 setex
    # conn.setex('xx',5,'yy')

    #5 psetex
    # conn.psetex('xx',5000,'yy')

    #6 mset 批量设置

    # conn.mset({'name':'lqz','age':19})

    # 7 mget(keys, *args)
    # print(conn.mget(['name','age']))
    # print(conn.mget('name','age'))

    #8 getset(name, value)
    # res=conn.getset('name','egon')

    #9 getrange


    # gbk: 2个字节表示一个字符
    # utf-8 3个字节表示一个字符
    # res=conn.getrange('name',0,0) # 前闭后闭区间
    # res=conn.getrange('name',0,2).decode('utf-8') # 前闭后闭区间
    # print(res)


    # 10 setrange
    # conn.setrange('name',2,'zzz')

    # 11 strlen 一个汉字,是3个字节
    # print(conn.strlen('name'))


    # 12 incr
    # print(conn.incr('age'))


    # 13 decr
    # conn.decr('age')

    # 14 append
    conn.append('xxxxxxx','nb')



    # print(res)
    conn.close()
  • 相关阅读:
    C
    B
    D
    I
    B
    E
    B
    L
    H
    bzoj3276磁力 两种要求下的最大值:分块or线段树+拓扑
  • 原文地址:https://www.cnblogs.com/DEJAVU888/p/14893972.html
Copyright © 2011-2022 走看看