Django组件介绍(二)
4.cookie和session
4.1http协议的特点
无状态保存:两次http请求之间没有任何的关联,(当用户已经登录一次时,下次客服端再次发送请求时,服务器不能知道账号是否登录)为了解决HTTP这个缺点,需要用到cookie
4.2 cookie协议
4.21 简介
具体的一个浏览器针对一个服务器存储的key-value
浏览器每次发请求时带着cookie(已经存储到磁盘上,失效时不会携带),而服务器可以通过set-cookice字段设置cookie
注意:这个cookie只要发送到这个服务器,无论是服务器的那个地址位置,都会携带。每个客户端的cookie是独立的,每个网站的cookie也是独立的,分开的;cookie存在硬盘上的
特点:Cookie大小上限为4KB,服务器最多在客户端保存20个cookie,浏览器最多可以保存300个cookie,不同浏览器之间的cookie不共享
4.22 cookie的设置与读取
设置cookie
respone.set_cookie(key,value)
函数
respone
是响应体,可以是HttpRespone()
,redirect()
,render()
返回的值
示例:
使用cookie保存用户登录状态和用户姓名
def login(request):
if request.method == "POST":
name = request.POST.get("user")
pwd = request.POST.get("pwd")
ret = Userinfo.objects.filter(user=name,pwd=pwd)
print(ret)
if ret:
respone = HttpResponse("OK")
respone.set_cookie("is_login",True)
respone.set_cookie("is_show",name)
return respone
else:
return render(request,"login.html")
else:
return render(request,"login.html")
注意:这里我们不直接返回响应体,而是通过给响应体设置cookie
传入键值对,第一个参数为键,第二个参数为值
获取cookie
request.COOKIE.get(key)
示例:
使用cookie读取用户登录状态,并记录用户登录时间
def index(request):
isLogin = request.COOKIES.get("is_login")
print(isLogin)
if isLogin:
name = request.COOKIES.get("is_show")
last_time = request.COOKIES.get("now","")
respone = render(request,"index.html",locals())
now = datetime.datetime.now().strftime("%Y-%m-%D %H:%M:%S")
respone.set_cookie("now",now)
return respone
else:
return redirect("/login/")
使用get
获取其中的键值对
注意:如果设置cookie时,浏览器存在该键值对,将会被覆盖
删除cookie
response.delete_cookie()
删除cookie
4.23 设置cookie相关的参数
max_age字段
设置超时参数,单位秒
respone.set_cookie("is_login",True,max_age=15)
代表这个cookie有效期只有十五秒,十五秒过后就会实现,客户端就不会发送这个cookie
默认有效期是浏览器开启状态
expire字段
也是设置超时时间
date = datetime.datetime(year=2018,month=9,day=19,hour=14,minute=25)
respone.set_cookie("is_show",name,expires=date)
设置到2018/9/19 22:25:0 过期
注意:datetime类型是按照0时区算,东八区(中国时间-8h)如果想修改当地市区,去settings.py
中设置时区为上海
TIME_ZONE = "Asia/ShangHai"
path字段
设置有效路径(默认根路径,所有路径都有效)设置在什么路径下视图函数才有效
respone.set_cookie("is_show",name,path="/index/")
只有index/路径才能访问这个cookie,其他路径不能访问
4.3 session流程简介
session是基于cookie实现的会话跟踪技术,而cookie本身也是会话跟踪技术
将cookie键值存到服务端,发给客户端的是一串字符串(相当于钥匙),可以在服务器中表中拿到相应的字典,然后取值
4.31 设置session步骤
request.session[key] = value
- 客户端请求cookie,浏览器使用session设置,将该键值对当做值(session-data),键为随机字符串(session-key),发给客户端
- 给响应体设置set_cookie,发给客户端的键值对,键为sessionid,值为生成的随机字符串
- django-session表生成这条记录,序列化后当值存储在表中
具体方法
request.session["is_login"] = True
request.session["user"] = name
使用[]方式,相当于设置字典键值的方式
4.32 读取session方法
data.get("is_login")
- 读客户端带来的cookie
- 从表中取出字典,然后get取出值
具体方法
isLogin = request.session["is_login"]
name = request.session.get("user")
4.33 更新session
该键的cookie存在时,更新;不存在则创建
4.34 删除session值
del request.session["is_login"]
4.35 清空session
request.session.flush()
4.36 session其他api
api | 功能 |
---|---|
get(key,default=None) | 获取键,没有则获取默认值 |
session_key | 用户session随机字符串 |
clear_expired() | 将所有session失效小于当前日期的数据删除 |
session.exists("session_key") | 查询数据库中是否有 |
session.delete("session_key") | 删除当前用户的所有session数值 |
4.37 session配置
写在settings文件中
配置信息 | 功能 |
---|---|
SESSION_COOKIE_NAME = “sessionid” | 给客户端设置的session的cookie键名 |
SESSION_COOKIE_PATH = "/" | session对于哪个路径有效 |
SESSION_COOKIE_AGE = 1209600 | 设置session的有效期多长(单位秒s) |
SESSION_COOKIE_AT_BROWSER_CLOSE = False | 是否等浏览器关闭后session过期 |
SESSION_SAVE_EVERY_REQUEST = False | 是否每次请求都保存session(修改默认之后才保存,默认) 简单说,如果该值为true,session有效期为7天,今天访问还有7天过期,明天访问,过期时间往后延迟一天 |
4.38 session项目案例
1.登录案例
记录用户登录信息
def index_session(request):
isLogin = request.session.get("is_login")
print(isLogin)
if isLogin:
name = request.session.get("user")
last_time = request.session.get("last_time")
return render(request,"index.html",locals())
else:
return redirect("/login_session/")
def login_session(request):
if request.method == "POST":
name = request.POST.get("user")
pwd = request.POST.get("pwd")
ret = Userinfo.objects.filter(user=name,pwd=pwd)
print(ret)
if ret:
request.session["is_login"] = True
request.session["user"] = name
import datetime
now = datetime.datetime.now().strftime("%Y-%m-%D %D:%M:%S")
request.session["last_time"] = now
return HttpResponse("OK")
else:
return render(request,"login.html")
else:
return render(request,"login.html")
2.验证码案例
5.Django用户认证组件
之前使用session做用户认证时,上个例子缺点是切换用户时只修改一个字段,造成用户记录混乱
如果我们想用django自带的用户认证模块,帮助我们认证和注册用户名和密码,我们就可以使用auth
模块
5.1 auth模块
功能:使用session记录登录验证状态,将其记录到用户表(django自带auth-user)
5.11 导入模块
from django.contrib import auth
5.12 用户认证API
auth.authenticate(username=username,password=pwd)
提供用户认证,判断用户名密码是否正确.
这个函数主要是将用户名和加密过后的密码存入数据库中
示例:user = auth.login(request,user)
5.13 创建用户对象
auth.login(request,user)
request将会创建一个属性名user,值当前登录对象;以后取登录对象可以直接取.user,没有登录取出来的是匿名用户对象,匿名用户对象可以打印出来的值
user相关属性 | 打印出来的值 |
---|---|
request.user.username | 用户名 |
request.user.id | 用户id |
request.user.is_anonymous | 是否为匿名对象 |
request.user.is_authenticated | 判断用户是否登录 |
这些方法不需要传值,可以直接在模板中使用。判断判断user是否登录,request.user.is_anonymous
和request.user.is_authenticated
都可以使用
5.14 用户注销API
auth.logout(request)
内部调用request.session.flush
主要用来清除cookie,注销用户
5.15 创建用户记录
User.objects.create_user()
创建普通用户
User.objects.create_superuser()
创建超级用户
传入相关字段即可
使用命令行创建相关用户,方法
创建超级用户:python manage.py createsuperuser
5.16 检查密码及验证密码
check_password(passwd)
可以检查密码是否符合标准,符合标准返回true
set_password()
修改密码
示例:
user = User.objects.get(username=user)
user.set_password(password=pwd)
user.save()
5.2 使用示例
用户登录,验证,注销操作
def index(request):
if request.user.is_anonymous:
return redirect("/login/")
return render(request,"index.html")
def login(request):
if request.method == "POST":
username = request.POST.get("username")
pwd = request.POST.get("pwd")
user = auth.authenticate(username=username,password=pwd)
if user:
return redirect("index.html")
return render(request,"login.html")
def logout(request):
auth.logout(request)
return redirect("/login/")
def register(request):
if request.method == "POST":
username = request.POST.get("username")
pwd = request.POST.get("pwd")
User.objects.create_user(username=username,password=pwd,email="") #可以用户创建用户记录
return redirect("/login/")
return render(request,"register.html")
5.3 基于用户登录装饰器
很多视图函数都要经过认证之后才能显示,所以我们给需要登录后才显示的视图函数加装饰器
5.31 导入装饰器
from django.contrib.auth.decoration import login_required
5.32 给需要验证的视图函数加装饰器
@login_required
def index(request):
return render(request,"index.html")
def login(request):
if request.method == "POST":
username = request.POST.get("username")
pwd = request.POST.get("pwd")
user = auth.authenticate(username=username,password=pwd)
if user:
auth.login(request,user)
next_url = request.GET.get("next","/index")
return redirect(next_url)
return render(request,"login.html")
def logout(request):
auth.logout(request)
return redirect("/login/")
def register(request):
if request.method == "POST":
username = request.POST.get("username")
pwd = request.POST.get("pwd")
User.objects.create_user(username=username,password=pwd,email="")
return redirect("/login/")
return render(request,"register.html")
@login_required
def look(request):
print("def look(request):")
return render(request,"look.html")
注意:使用之前需要在settings.py
中设置LOGIN_URL=“/login/”
-------这里需要注意一点,在login
视图函数需要修改
登录成功后跳转到原来页面(登录页面将自动传入一个next值,用来存储原来页面url)
auth.login(request,user)
next_url = request.GET.get("next","/index")
return redirect(next_url)
装饰器函数执行登录成功时时浏览器跳转到相应页面,会传入一个值,即next
存储原页面的url,我们需要将其获取然后跳转