2021-07-28 前端登录注册功能 redis的安装和使用 redis字符串类型 字典类型 列表类型 通用操作 管道 django使用redis

昨日回顾

1 验证手机号是否存在接口
2 使用腾讯云发送短信
	-api,sdk
    -两个 :3版本和2版本
    	-3版本不仅仅有发送短信,腾讯云的其他服务,都集成进去了
        -2版本只有发送短信功能
    -二次封装:更简单的使用腾讯云sdk发送短信
    
    -发送短信接口
    	-缓存验证码
        -短信发送的同步和异步
        
3 短信登录接口
	-前端传递过来:手机号和验证码
    -把验证码取出来,校验验证码是否正确
    -根据手机号查到用户,签发token,返回
    
4 短信注册接口
	-前端传递:手机号,验证码,密码
    -校验验证码是否正确
    -重写create方法:User.object.create_user()
    

    
   
    
    
5 发送短信频率限制

今日内容

1 前端登录,注册功能

1.1 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="login_pwd">登录</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="sms_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')
            },
            change_login_method(method) {
                this.login_method = method;
            },
            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 = '';
                            this.is_send = false;
                        }
                    });
                    return false;
                }

                //调用后端手机号是否存在接口,判断
                this.$http.get(this.$settings.base_url + '/api/user/check_mobile/?mobile=' + this.mobile).then(res => {
                    if (res.data.code == 100 && res.data.exisit) {
                        // this.$message()
                        this.is_send = true;
                    } else {
                        this.$message('该手机号未注册,请先去注册')
                        this.$emit('go')
                    }
                })
            },
            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.$settings.base_url + '/api/user/send_sms/?mobile=' + this.mobile).then(res => {
                    this.$message(res.data.msg)
                })
            },
            login_pwd() {
                if (this.username && this.password) {

                    this.$http.post(this.$settings.base_url + '/api/user/login/', {
                        username: this.username,
                        password: this.password
                    }).then(res => {
                        if (res.data.code == 100) {
                            // 把用户名和token放到cookie中(s:秒,d:天,m:月)
                            this.$cookie.set('token', res.data.token, '7d')
                            this.$cookie.set('username', res.data.username, '7d')
                            //关闭登录框
                            this.$emit('close')

                        } else {
                            this.$message({
                                message: res.data.msg[0],
                                type: 'error'
                            })
                        }
                    })

                } else {
                    this.$message({
                        message: '用户名或密码没有填',
                        type: 'warning'
                    })
                }
            },
            sms_login(){
                if (this.mobile && this.sms) {

                    this.$http.post(this.$settings.base_url + '/api/user/mobile_login/', {
                        mobile: this.mobile,
                        code: this.sms
                    }).then(res => {
                        if (res.data.code == 100) {
                            // 把用户名和token放到cookie中(s:秒,d:天,m:月)
                            this.$cookie.set('token', res.data.token, '7d')
                            this.$cookie.set('username', res.data.username, '7d')
                            //关闭登录框
                            this.$emit('close')

                        } else {
                            this.$message({
                                message: res.data.msg[0],
                                type: 'error'
                            })
                        }
                    })

                } else {
                    this.$message({
                        message: '手机号或验证码没有填',
                        type: 'warning'
                    })
                }
            },
        }


    }
</script>


<style scoped>

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

    .box {
        width: 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;
        width: 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 {
        width: 100%;
        font-size: 18px;
    }

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

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

</style>

1.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.$http.get(this.$settings.base_url + '/api/user/check_mobile/?mobile=' + this.mobile).then(res => {
                    if (res.data.code == 100 && res.data.exisit) {
                        this.$message('该手机号已经注册,请先去直接登录')
                        // this.mobile=''
                        this.$emit('go')
                    } else {
                        this.is_send = true;

                    }
                })

            },
            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.$settings.base_url + '/api/user/send_sms/?mobile=' + this.mobile).then(res => {
                    this.$message(res.data.msg)
                })
            },
            register(){
                    if (this.mobile && this.sms && this.password) {

                    this.$http.post(this.$settings.base_url + '/api/user/register/', {
                        mobile: this.mobile,
                        code: this.sms,
                        password:this.password
                    }).then(res => {
                        if (res.data.code == 100) {
                            //跳转到登录页面
                            this.$emit('go')

                        } else {
                            this.$message({
                                message: res.data.msg[0],
                                type: 'error'
                            })
                        }
                    })

                } else {
                    this.$message({
                        message: '手机号或验证码没有填',
                        type: 'warning'
                    })
                }
            }
        }
    }
</script>

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

    .box {
        width: 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;
        width: 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 {
        width: 100%;
        font-size: 18px;
    }

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

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

2 redis介绍和安装

# https://www.cnblogs.com/liuqingzheng/articles/9833534.html

# redis:是一个key-value存储系统,非关系型数据库(nosql数据库),数据存在于内存中,缓存数据库
# redis支持5大数据类型:字符串,列表,hash(字典),集合,有序集合
# 使用Redis有哪些好处
	-速度快:缓存数据库
    -支持丰富数据类型:5大数据类型
    -支持事务:通过管道支持(单实例上有效)
    -丰富的特性:可用于缓存,消息队列,按key设置过期时间,过期后将会自动删除
    
# redis相比memcached有哪些优势
	-都是内存数据库
    -redis类型丰富,5大类型,memcached只支持字符串类型
    -redis支持持久化,memcached不支持持久化
    -redis速度比mencached快
    
    
# 特点
	可以持久化
	单线程,单进程
    	-redis最新版本是6.x
        -6.x之前是单线程,单进程
# redis单线程为什么这么快?并发量:10w,6w左右
	-1 纯内存操作
    -2 使用了io多路复用模型(epoll   select)
    -3 因为是单线程,不存在线程间切换,节省资源
# 服务:客户端,服务端(跟mysql一样, 是存数据的地方)


# 安装:
	-redis使用c语言写的,开源,,我们不支持windows,第三方,基于redis源码,自行修改,编译成windows平台可以运行的(win平台:维护到 3.x版本),咱们现在讲,以3.x为例
    
# 官网
	http://redis.cn/
    -官网提供了c源码,需要自行下载,编译
    -win平台,自己找一个安装包(不是官方提供的)https://github.com/microsoftarchive/redis
        -Redis-x64-3.2.100.msi:一路下一步
        -图形化界面的客户端:redis-desktop-manager:一开始免费,后来收费了:一路下一步
        
    -监听端口默认是:6379
   

# 启动redis服务
	-第一种:在任意路径下敲:redis-server    # 等同于mysqld
    -第二种:win平台,已经做成了服务,把服务启动即可
    	-"D:\Program Files\Redis\redis-server.exe" --service-run "D:\Program Files\Redis\redis.windows-service.conf"
# 客户端连接
	-第一种方式:在任意路径下敲:redis-cli -h 127.0.0.1 -p 6379   # 等同于  mysql -h -P
    	-如果连本地的6379端口,直接敲redis-cli
    -使用客户端连接
    -使用python操作:pip3 install redis

1.2 普通连接和连接池

# from redis import Redis

### 普通连接
# 拿到一个redis连接
# conn=Redis(host='127.0.0.1',port=6380)
# # conn=Redis()
#
# # 操作redis
# conn.set('name','lqz')
#
# conn.close()


###redis连接池

# import redis
#
# #拿到一个连接数为3的连接池
# # 把POOL做成单例:把它以模块导入方式
# POOL=redis.ConnectionPool(max_connections=3,host='127.0.0.1', port=6380)

# # 从连接池中拿出一个连接,给conn
# conn=redis.Redis(connection_pool=POOL)
#
# conn.set('age',19)
# conn.close()  # 不是关闭连接,把该连接,放回到连接池

#####把POOL以单例形式使用

import redis

from pool import POOL  # 以模块形式导入,是天然单例
conn=redis.Redis(connection_pool=POOL)
# conn2=redis.Redis(connection_pool=POOL)
# conn3=redis.Redis(connection_pool=POOL)
# conn4=redis.Redis(connection_pool=POOL)
# conn5=redis.Redis(connection_pool=POOL)
# conn6=redis.Redis(connection_pool=POOL)

conn.set('age',19)
conn.close()  # 不是关闭连接,把该连接,放回到连接池

import redis

#拿到一个连接数为3的连接池
# 把POOL做成单例:把它以模块导入方式
POOL=redis.ConnectionPool(max_connections=3,host='127.0.0.1', port=6380)

3 redis 5大数据类型之字符串

'''
set(name, value, ex=None, px=None, nx=False, xx=False)       重点
setnx(name, value)
setex(name, value, time)
psetex(name, time_ms, value)
mset(*args, **kwargs)         重点
get(name)                    重点
mget(keys, *args)             重点
getset(name, value)
getrange(key, start, end)
setrange(name, offset, value)
setbit(name, offset, value)
getbit(name, offset)
bitcount(key, start=None, end=None)

strlen(name)                     重点
incr(self, name, amount=1)            重点
incrbyfloat(self, name, amount=1.0)
decr(self, name, amount=1)
append(key, value)
'''


import redis

conn=redis.Redis()

# set:放字符串值
'''
ex,过期时间(秒)
px,过期时间(毫秒)
nx,如果设置为True,则只有name不存在时,当前set操作才执行,值存在,就修改不了,执行没效果
xx,如果设置为True,则只有name存在时,当前set操作才执行,值存在才能修改,值不存在,不会设置新值
'''
# conn.set('name','lqz')
# res=conn.set('name','lqz',ex=3)
# res=conn.set('name','lqz',px=3000)
# res=conn.set('name','lqz')
# res=conn.set('name','egon')
# res=conn.set('name','lqz',nx=True)
# res=conn.set('name','19',xx=True)


# get 获取值
# res=conn.get('name')

# mset 批量设置值

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

# mget  批量获取值
# res=conn.mget(['name','age'])
# res=conn.mget('name','age')

# conn.setex(name, value, time)
# conn.psetex(name, time_ms, value)
# conn.set(name, valeu, px=time)

# res=conn.getset('name', '刘亦菲')


# res=conn.getrange('name',3,5)  #前闭后闭区间  拿到 亦 这个字   拿字节
#
# print(str(res,encoding='utf-8'))


# res=conn.setrange('name',0,'lqzzzzzzz')
# res=conn.setrange('name',0,'qq')


##获取和设置比特位
# setbit(name, offset, value)
# getbit(name, offset)


# print(conn.getbit('name',3))
# conn.setbit('name',0,1)
# print(conn.getbit('name',0))

# print(conn.strlen('name'))  # 指的是字节     获取字节长度

# conn.incr('age')   # 让该键自增1
# conn.incrby('age',3)   # 让该键自增3
# conn.incrbyfloat('age', amount=1.1)


conn.append('name', 'nb')

conn.close()

4 redis 5大数据类型之Hash


5 redis 5大数据类型之列表


6 其他操作

7 管道

8 django使用redis

# 第一种:通用方式(任何web框架都可以)

# 第二种:django提供的
	-在配置文件中配置
    	CACHES = {
            "default": {
                "BACKEND": "django_redis.cache.RedisCache",
                "LOCATION": "redis://127.0.0.1:6379",
                "OPTIONS": {
                    "CLIENT_CLASS": "django_redis.client.DefaultClient",
                    "CONNECTION_POOL_KWARGS": {"max_connections": 100}  # 连接池大小为100
                    # "PASSWORD": "123",
                }
            }
        }
    -安装django_redis模块
    -使用
    from django_redis import get_redis_connection
    def index(request):
        conn=get_redis_connection()
        res=conn.get('name')
        print(res)
        return HttpResponse('okkkkk')
    
   -一旦这样配置,django中的缓存,也用redis
	cache.set('key',python的任意对象)
上一篇:验证短信登录或注册


下一篇:jquery mobile创建个人中心界面