文章目录
- 五、状态保持
- 5.1 Django中状态保持
- 5.1.1 状态保持概述
- 5.1.2 Cookie
- 5.1.2.1 Cookie的用处:
- 5.1.2.1 Cookie的特点:
- 5.1.2.1 Cookie的操作:
- 5.1.3 session
- 5.1.3.1 Session的特点:
- 5.1.3.2 Session依赖于Cookie
- 5.1.3.3 存储方式
- 5.1.3.4 session的对象及方法
- 5.1.3.5 使用Redis存储Session
- 5.2 login()方法介绍
- 5.3 login()方法登入注册用户
- 5.3.1 windows安装redis
- 5.3.2 将Redis安装成Windows服务
- 5.4 查看状态保持结果
- 5.4.1 查看redis数据库session内容
- 5.4.1 查看浏览器cookie数据
- 六、判断用户名是否重复注册
- 6.1 目的
- 6.2 步骤(套路)
- 6.2.1 用户名重复注册逻辑分析
- 6.2.2 用户名重复注册接口设计和定义
- 6.2.3 用户名重复注册后端逻辑
- 6.2.3.1 定义状态码文件 response_code.py
- 6.2.3.2 定义路由
- 6.2.3.3 定义视图文件 view.py
- 6.2.4 用户名重复注册前端逻辑
- 6.2.4.1 使用axios发送Ajax请求的步骤
- 6.2.4.2 axios发送Ajax请求流程
五、状态保持
5.1 Django中状态保持
5.1.1 状态保持概述
浏览器请求服务器是无状态的。无状态指一次用户请求时,浏览器、服务器无法知道之前这个用户做过什么,每次请求都是一次新的请求。无状态的应用层面的原因是:浏览器和服务器之间的通信都遵守HTTP协议。根本原因是:浏览器与服务器是使用Socket套接字进行通信的,服务器将请求结果返回给浏览器之后,会关闭当前的Socket连接,而且服务器也会在处理页面完毕之后销毁页面对象。
有时需要保持下来用户浏览的状态,比如用户是否登录过,浏览过哪些商品等。 实现状态保持主要有两种方式:
- 在客户端存储信息使用Cookie。
- 在服务器端存储信息使用Session。
5.1.2 Cookie
5.1.2.1 Cookie的用处:
- 记录用户的登录状态
- 购物时将购物的信息记录cookie,便于用户在不同网页选择不同商品,付款时方便提取信息
5.1.2.1 Cookie的特点:
- cookie是由服务器生成,存储在浏览器端的一小段文本信息。
- 以键值对方式进行存储。
- 通过浏览器访问一个网站时,会将本地存储的跟网站相关的所有cookie信息发送给该网站的服务器。
- cookie是基于域名安全的。
- Cookie是有过期时间的,如果不指定,默认关闭浏览器之后cookie就会过期。
5.1.2.1 Cookie的操作:
-
获取值
使用request.COOKIE[‘res’] -
赋值
使用response.set_cookie(‘res’, res, max_aeg, expires)- max_age是一个整数,表示在指定秒数后过期。
- expires是一个datetime或timedelta对象,会话将在这个指定的日期/时间过期。
- max_age与expires二选一。
如果不指定过期时间,在关闭浏览器时cookie会过期。
5.1.3 session
对于敏感、重要的信息,建议要储在服务器端,不能存储在浏览器中,如用户名、余额、等级、验证码等信息。
开启项目中的中间件默认开启
打开settings.py文件,在项MIDDLEWARE_CLASSES中启用Session中间件。默认开启
5.1.3.1 Session的特点:
- 在服务器端进行状态保持的方案就是Session。
- session是以键值对进行存储的。
- session依赖于cookie。
- session也是有过期时间,如果不指定,默认两周就会过期。
5.1.3.2 Session依赖于Cookie
问:所有请求者的Session都会存储在服务器中,服务器如何区分请求者和Session数据的对应关系呢?
答:在使用Session后,会在Cookie中存储一个sessionid的数据,每次请求时浏览器都会将这个数据发给服务器,服务器在接收到sessionid后,会根据这个值找出这个请求者的Session。
结果:如果想使用Session,浏览器必须支持Cookie,否则就无法使用Session了。
存储Session时,键与Cookie中的sessionid相同,值是开发人员设置的键值对信息,进行了base64编码,过期时间由开发人员设置。
5.1.3.3 存储方式
打开test3/settings.py文件,设置SESSION_ENGINE项指定Session数据存储的方式,可以存储在数据库、缓存、Redis等。
存储在数据库中,如下设置可以写,也可以不写,这是默认存储方式。(需要连接数据库并且已经存在对应的存放session信息的表)
SESSION_ENGINE='django.contrib.sessions.backends.db'
存储在缓存中:存储在本机内存中,如果丢失则不能找回,比数据库的方式读写更快。
SESSION_ENGINE='django.contrib.sessions.backends.cache'
混合存储:优先从本机内存中存取,如果没有则从数据库中存取。
SESSION_ENGINE='django.contrib.sessions.backends.cached_db'
5.1.3.4 session的对象及方法
以键值对的格式写会话。
request.session['键']=值
根据键读取值。
request.session.get('键',默认值)
清除所有会话,在存储中删除值部分。
request.session.clear()
清除会话数据,在存储中删除会话的整条数据。
request.session.flush()
删除会话中的指定键及值,在存储中只删除某个键及对应的值。
del request.session['键']
设置会话的超时时间,如果没有指定过期时间则两个星期后过期。
- 如果value是一个整数,会话将在value秒没有活动后过期。
- 如果value为0,那么用户会话的Cookie将在用户的浏览器关闭时过期。
- 如果value为None,那么会话永不过期。
request.session.set_expiry(value)
5.1.3.5 使用Redis存储Session
将服务器端的session信息保存到数据库的相关配置
安装包。
pip install django-redis-sessions
修改test3/settings文件,增加如下项:
SESSION_ENGINE = 'redis_sessions.session'
SESSION_REDIS_HOST = 'localhost'
SESSION_REDIS_PORT = 6379
SESSION_REDIS_DB = 2
SESSION_REDIS_PASSWORD = ''
SESSION_REDIS_PREFIX = 'session'’
实现用户注册成功就表示注册用户已经登入到美多商城系统,不用再跳转到登录页面重新登录一次。
5.2 login()方法介绍
django认证系统内部方法
- 用户登入本质:
- 状态保持
- 将通过认证的用户的唯一标志信息(比如:用户名)写入到当前浏览器的cookie和服务器的session中
- login()方法:
- Django用户认证系统提供了login()方法
- 封装了写入session的操作,帮助开发者快速登入一个用户,并实现状态保持。
- login()位置:django.contrib.auth.init.py文件中。login(request, user, backend=None)
- 状态保持session数据库存储的位置:Redis数据库的1号库,前期已经配置好了
SESSION_ENGINE = “django.contrib.sessions.backends.cache”
SESSION_CACHE_ALIAS = “session”
5.3 login()方法登入注册用户
状态保持,login方法的session保存到redis数据库,如果这一步卡死过不去,是因为redis数据库没有安装或配置好
5.3.1 windows安装redis
Redis不支持Windows!在它官网写得很清楚。但是开发环境一般是Windows系统。为了方便开发和调试,需要在Windows中安装Redis。微软自己弄了Redis的Windows版本。
打开https://github.com/MSOpenTech/redis/releases下载msi安装包。
该版本是64位。
安装msi过程中,有个选项是否加入系统环境变量,记得勾上。一路下一步,安装。
完成之后打开cmd,输入redis-server命令查看是否可以使用,不可以则重启一下即可。
直接输入redis-server命令使用的配置文件是安装目录下的redis.windows.conf文件。 若提示错误 “ConnectionError: Error 10061 connecting to None:6379”,可打开cmd连续输入如下命令:
redis-cli shutdown
redis-server
5.3.2 将Redis安装成Windows服务
虽然在上面的步骤中启动了redis,但是只要一关闭cmd窗口,redis服务端就会消失。所以要把redis设置成Windows下面的服务,这样,就不需要一直开着cmd窗口了。
- 输入服务命令,进入redis解压目录以后,输入服务命令:redis-server --service-install redis.windows-service.config --loglevel verbose
输入命令之后按下回车键,如果没有报错,表示安装成功,刷新Windows服务,此时会看到redis服务:
如果此时Redis服务没有启动,可以使用redis-serer --service-start命令启动服务。 - 常用的redis服务命令
http://doc.redisfans.com/index.html
安装服务:redis-server --service-install
卸载服务:redis-server --service-uninstall
启动服务:redis-server --service-start
停止服务:redis-server --service-stop
info #查看服务器信息
select #选择数据库索引 select 1
flushall #清空全部数据
flushdb #清空当前索引的数据库
slaveof <服务器> <端口> #设置为从服务器
slaveof no one #设置为主服务器
shutdown #关闭服务
5.4 查看状态保持结果
5.4.1 查看redis数据库session内容
cmd,启动redis服务器:redis-server
另开一个cmd,启动redis服务端:redis-cli
redis-cli
select 1
keys *
get :1:django.contrib.sessions.cachea3pbpgu2temlfkea1mtwf45gbj1svv5k
5.4.1 查看浏览器cookie数据
sesseionid: a3pbpgu2temlfkea1mtwf45gbj1svv5k,与redis服务器中session的key一致
六、判断用户名是否重复注册
6.1 目的
- 判断用户名是否重复注册的后端逻辑
- 学会使用axios发送Ajax请求,并实现局部刷新效果
6.2 步骤(套路)
6.2.1 用户名重复注册逻辑分析
6.2.2 用户名重复注册接口设计和定义
6.2.3 用户名重复注册后端逻辑
6.2.3.1 定义状态码文件 response_code.py
# coding:utf-8
class RETCODE:
OK = "0"
IMAGECODEERR = "4001"
THROTTLINGERR = "4002"
NECESSARYPARAMEERR = "4003"
USERERR = "4004"
PWDERR = "4005"
CPWDERR = "4006"
MOBILEERR = "4007"
SMSCODERR = "4008"
ALLOWERR = "4009"
SESSIONERR = "4101"
DBERR = "5000"
EMAILERR = "5001"
TELERR = "5002"
NODATAERR = "5003"
NEWPWDERR = "5004"
OPENIDERR = "5005"
PARAMERR = "5006"
STOCKERR = "5007"
err_msg = {
RETCODE.OK : u"成功",
RETCODE.IMAGECODEERR : u"图形验证码错误",
RETCODE.THROTTLINGERR : u"访问过于频繁",
RETCODE.NECESSARYPARAMEERR : u"缺少必传参数",
RETCODE.USERERR : u"用户名错误",
RETCODE.PWDERR : u"密码错误",
RETCODE.CPWDERR : u"密码不一致",
RETCODE.MOBILEERR : u"手机号错误",
RETCODE.SMSCODERR : u"短信验证码错误",
RETCODE.ALLOWERR : u"未勾选协议",
RETCODE.SESSIONERR : u"用户未登录",
RETCODE.DBERR : u"数据错误",
RETCODE.EMAILERR : u"邮箱错误",
RETCODE.TELERR : u"固定电话错误",
RETCODE.NODATAERR : u"无数据",
RETCODE.NEWPWDERR : u"新密码数据",
RETCODE.OPENIDERR : u"无效的openid",
RETCODE.PARAMERR : u"参数错误",
RETCODE.STOCKERR : u"stock错误",
}
6.2.3.2 定义路由
from django.urls import path, re_path
from . import views
app_name = 'users'
urlpatterns = [
# 用户注册: reverse(users:register) == '/register/'
path('register/', views.ResgisterView.as_view(), name='register'),
# 判断用户名是否重复注册,re_path路由正则校验,响应json数据,不需要重定向,也就不需要命名空间
re_path(r'^usernames/(?P<username>[a-zA-Z0-9-_]{5,20})/count/$', views.UsernameCountView.as_view()),
]
6.2.3.3 定义视图文件 view.py
from meiduo_mall.utils.response_code import RETCODE
class UsernameCountView(View):
""" 判断用户名是否重复注册 """
def get(self, request, username):
""" 参数:username(从路由中通过正则提取),响应数据:json """
# 接收和校验参数:路由利用正则校验,已经实现
# 主体业务逻辑:使用username查询数据库对应的记录条数
count = User.objects.filter(username=username).count() # filter返回结果集,.count取出条数
# 相应结果
return http.JsonResponse({'code': RETCODE.OK, 'errmsg': 'OK', 'count': count})
6.2.4 用户名重复注册前端逻辑
6.2.4.1 使用axios发送Ajax请求的步骤
- html文件中导入axios库
- js文件中axios.get(‘url’,‘请求头(可以省略)’)
- 请求成功用 .then(function(response){}) 接收,箭头函数写法:.then(response => {})
- 请求失败用 .catch(function(error){}) 接收,箭头函数写法:.catch(error => {})
6.2.4.2 axios发送Ajax请求流程
// 如果用户名符合上面的条件,然后判断用户名是否重复注册
if (this.error_name == false) { //用户名满足条件
let url = '/usernames/'+ this.username +'/count/';
axios.get(url, {
responseType: 'json'
})
.then(response => {
if (response.data.count ==1) { //用户名已存在
this.error_name_message = '用户名已存在';
this.error_name = true;
} else { //用户名不存在
this.error_name = false;
}
})
.catch(error => {
console.log(error.response);
})
}