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()
  • 相关阅读:
    Leetcode 1489找到最小生成树李关键边和伪关键边
    Leetcode 113 路径总和 II
    hdu 1223 还是畅通工程
    hdu 1087 Super Jumping! Jumping! Jumping!
    hdu 1008 Elevator
    hdu 1037 Keep on Truckin'
    湖工oj 1241 畅通工程
    湖工oj 1162 大武汉局域网
    hdu 2057 A + B Again
    poj 2236 Wireless Network
  • 原文地址:https://www.cnblogs.com/DEJAVU888/p/14893972.html
Copyright © 2011-2022 走看看