Django详解之四、cookie和session
一、使用背景
思路 简单的后台管理:对人员的管理 1、 登录注册 2、 老师 班级管理 学院管理 3、 增删改查 开发: 1、 定义数据库表结构 a) 表结构关系 i. class classes(models.Model): 1. caption=models.Charfield(max_length=32) class student(models.Model): name=models.CharField(max_length=32) cls=models.Foreignkey(‘classes’) username=models.CharFeild(max_length=32) password=models.CharFeild(max_length=32) class Teacher(models.Model): name=models.Charfield(max_length=32) username=models.CharFeild(max_length=32) password=models.CharFeild(max_length=32) cls=models.ManytoMany(‘classes’) 第三张表 登录注册 提交表单: -form -Ajax 登录 -成功:记住状态<->保持会话 -失败:错误提示
依据上面思路来讲解cookie以及session
一、cookie
cookie:
1、 保存在用户浏览器
2、 可以主动清除
3、 也可以被“伪造”
4、 跨域是不共享的
5、 浏览器可以设置不接收cookie
6、 给cookie设置超时时间 max_age=””(秒)
cookie是什么?
就是保存在浏览器端的键值对,可以利用来做登录
下面是设置cookie和获取cookie的操作
from django.shortcuts import render,HttpResponse,redirect # Create your views here. from app01 import models def login(request): message='' if request.method=='POST': user=request.POST.get('user') pwd=request.POST.get('pwd') if user=="a" and pwd=="a": #cookie req=redirect("/index.html") req.set_cookie("username",user) return req else: message = "用户名或者密码错误" return render(request,'login.html',{"msg":message}) def index(request): #如果用户已经登录,获取当前登录的用户名 #否则,返回登录页面 username=request.COOKIES.get('username') print(username) if username: render(request, 'index.html', {"username": username}) else: return redirect("/login.html")
下面例子:
首先写一个登录页面,然后用户登录就会跳转到页面, 谁登录的就会显示欢迎谁
根据MTV模式首先配置M
1、首先创建数据库表
from django.db import models ''' 这里创建四张表 一张班级 一张学生 一张教师,教师和班级之间的关系是多对多 一张管理员 ''' # Create your models here. class Classes(models.Model): caption=models.CharField(max_length=32) class Student(models.Model): name=models.CharField(max_length=32) cls=models.ForeignKey('Classes') class Teacher(models.Model): name=models.CharField(max_length=32) cls=models.ManyToManyField('Classes') class Administrator(models.Model): username=models.CharField(max_length=32) password=models.CharField(max_length=32)
2、配置连接mysql
在setings中配置:
# DATABASES = { # 'default': { # 'ENGINE': 'django.db.backends.sqlite3', # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), # } # } DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'user_django', 'USER':'root', 'PASSWORD':'123456', 'HOST':"", 'PORT':'3306' } }
然后配置app01
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01', ]
之后init文件中导入pymysql
import pymysql pymysql.install_as_MySQLdb()
2、配置T
配置登录后的欢迎页面index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1> hello {{ username }} </h1> </body> </html>
以及用户登录页面login.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="login.html" method="post"> {% csrf_token %} //这里是做csrf用的 <div> <label for="user">用户名:</label> <input type="text" id="user" name="user"/> </div> <div> <label for="pwd">密 码: </label> <input type="password" name="pwd"/> </div> <div> <label></label> <input type="submit" value="登录"/> <span style="color: red">{{ msg }}</span> </div> </form> </body> </html>
3、配置MTV中的V
首先配置urls
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r"^login.html$",views.login), url(r"^index.html$",views.index) ]
之后在配置view视图函数
from django.shortcuts import render,HttpResponse,redirect # Create your views here. from app01 import models def login(request): # models.Administrator.objects.create( # username="pyrene", # password="pyrene" # ) message='' if request.method=='POST': user=request.POST.get('user') pwd=request.POST.get('pwd') c=models.Administrator.objects.filter(username=user,password=pwd).count() if c: #cookie req=redirect("/index.html") req.set_cookie("username",user) return req else: message = "用户名或者密码错误" return render(request,'login.html',{"msg":message}) def index(request): #如果用户已经登录,获取当前登录的用户名 #否则,返回登录页面 username=request.COOKIES.get('username') print(username) if username: return render(request, 'index.html', {"username": username}) else: return redirect("/login.html")
往数据库中添加数据,然后连接http://127.0.0.1:8000/login.html,就把数据添加到数据库中,
之后注释掉添加的语句,直接利用cookie来判断用户是否登录
二、cookie中的参数
def set_cookie(self, key, value='', max_age=None, expires=None, path='/', domain=None, secure=False, httponly=False):
max_age设置秒
path: 设置路径
/ 表示,全局生效
/xxx/ 表示,只有当前url生效
domian:设置域名
obj.set_cookie(“k”,”v”,domain=””)
假如这里domain=”pyrene.com”并且设置cookie为k1,v1
这个时候访问下面二级域名www.pyrene.com以及crn.pyrene.com 的时候下面的二级域名里面没有cookie就会去pyrene.com中寻找二级域名,也就能获取
如果domain=www.pyrene.com并且设置cookie为k2,v2
这个时候如果访问www.pyrene.com/pyrene 这样就能够获取cookie
但是如果要访问crn.pyrene.com 这样是获取不到cookie的
expires:也是设置超时时间的
obj.set_cookie(“k1”,”v1”)
v=datatime.datetime.utcnow()+datetime.timedelta(seconds=10)
obj.set_cookie(“k2”,”v2”,expires=v)
如:
def test(request): import datetime v=datetime.datetime.utcnow()+datetime.timedelta(seconds=10) obj=HttpResponse("ok") obj.set_cookie("k2","v1",expires=v) return obj def xiaohu(request): v=request.COOKIES.get("k2") return HttpResponse(v)
url配置:
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r"^login.html$",views.login), url(r"^index.html$",views.index), url(r"^test.html$",views.test), url(r"^xiaohu.html$",views.xiaohu) ]
当用户访问test.html之后再访问xiaohu.html的时候就会获取到k2对应的值,但是当10秒钟过后这个值就会消失,那么xiaohu这个url页面就会显null
三、利用js来设置获取cookie
客户端浏览器操作cookie两种方式:
dom操作 --》麻烦
jquery插件 --》
jquery.cookie.js
jquery.js
参数 expires:不仅仅支持数字 10
也支持d=new Date()
d.setDate(d.getDate()+1)
例子:
首先在settings中加入静态文件配置
STATIC_URL = '/static/' STATICFILES_DIRS=( os.path.join(BASE_DIR,"static"), ) 之后在static中引入两个文件
然后配置urls
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r"^login.html$",views.login), url(r"^index.html$",views.index), url(r"^test.html$",views.test), url(r"^xiaohu.html$",views.xiaohu), url(r"^js_cookie.html$",views.js_cookie) ]
在views中写入视图函数
def js_cookie(request): print(request.COOKIES) obj=render(request,"js_cookie.html") obj.set_cookie("k1","v1") return obj
然后在templates中写入js_cookie.js文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="/static/jquery-2.1.4.min.js"></script> <script src="/static/jquery.cookie.js"></script> <script> //$.cookie() //一个参数:$.cookie(k) 获取值 //两个参数:$.cookie(k.v) 设置值 $.cookie("k","v",{"path":"/index.html"}) </script> </head> <body> </body> </html>
然后就可以在js_cookie.html进行操作cookie
语法:
$.cookie(“k”,”v”,{ “path”:”/xx”})
其中字典中是参数
总结:
为什么有cookie:
没有cookie会把后台信息暴露出来
cookie是放入到响应头里面的。
1、浏览器连接把cookie放入到请求头发送给服务器,2、服务器把cookie放入到响应头中发给浏览器中,3、浏览器把客户端中的cookie放入到请求头发给服务器
cookie的三个重要点:
1、 客户端可以设置
2、 服务端可以设置
3、 保存在客户端
cookie的应用:
登录认证
=====================》不敏感cookie的方法
set_cookie,request.COOKIES.get()
普通cookie
如果有敏感信息(直接看到)就不适合放入里面
签名cookie
set_signed_cookie get_signed_cookie
签名(加密)cookie,敏感信息(可能会被解密)
如果有敏感信息就不要放入到上面的两种cookie中
=====================》如果有敏感cookie的时候就需要用下面方法
session
session是什么:
session是服务器端的一个键值对
session内部机制依赖于cookie
因为django中内部自己封装了session,所以直接可以用
设置session:
request.session[“is_login”]=true
获取session注意这里用小括号
is_login=request.session.get(“is_login”)
session流程:
第一次:用户访问服务器,服务器会把session随机字符串(request.session[‘is_login’]=False)以及前端页面返回给用户
第二次:用户把账户密码和session随机字符串发送给服务器,服务器收到之后对比成功就返回给客户端(request.session[‘is_login’]=True)
第三次:客户端跳转页面会连接服务器对比session,比对成功就正常跳转,没有就跳转到登录页面
下面是用户登录的例子:
index.html,登录后返回的页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1> hello {{ username }} </h1> </body> </html>
login.html登录页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="login.html" method="post"> {% csrf_token %} <div> <label for="user">用户名:</label> <input type="text" id="user" name="user"/> </div> <div> <label for="pwd">密 码: </label> <input type="password" name="pwd"/> </div> <div> <label></label> <input type="submit" value="登录"/> <span style="color: red">{{ msg }}</span> </div> </form> </body> </html>
后台views视图函数中的定义session登录
from django.shortcuts import render,HttpResponse,redirect # Create your views here. from app01 import models def login(request): # models.Administrator.objects.create( # username="pyrene", # password="pyrene" # ) message='' if request.method=='POST': user=request.POST.get('user') pwd=request.POST.get('pwd') c = models.Administrator.objects.filter(username=user, password=pwd).count() if c: request.session['is_login'] = True request.session["username"]=user rep = redirect('/index.html') return rep else: message = "用户名或者密码错误" return render(request,'login.html',{"msg":message}) def index(request): is_login=request.session.get("is_login") if is_login: current_user=request.session.get("username") return render(request,"index.html",{"username":current_user}) else: return redirect("/login.html")
注意这里设置了session就是在数据库中生成了session这张表,然后把定义的session等装到数据库中
这里的session内部原理和tornado的session原理是一样的,要想详细了解,请看tornado自定义session
如果出现下面这个错误,应该是写session的小括号写成了[],中括号是获取下标的
'method' object is not subscriptable
session使用一、
session基本操作使用 def index(request): # 获取、设置、删除Session中数据 request.session['k1'] 获取值 request.session.get('k1',None) 获取值,没有没空 request.session['k1'] = 123 设置值。存不存在都设置成功 request.session.setdefault('k1',123) # 存在则不设置 del request.session['k1'] 删除session # 所有 键、值、键值对 request.session.keys() request.session.values() request.session.items() request.session.iterkeys() 迭代 request.session.itervalues() request.session.iteritems() # 获取当前用户session的随机字符串 request.session.session_key # 将所有Session失效日期小于当前日期的数据删除 request.session.clear_expired() # 检查 用户session的随机字符串 在数据库中是否 request.session.exists("session_key") # 删除当前用户的所有Session数据 request.session.delete("session_key") request.session.set_expiry(value) * 如果value是个整数,session会在些秒数后失效。 * 如果value是个datatime或timedelta,session就会在这个时间后失效。 * 如果value是0,用户关闭浏览器session就会失效。 * 如果value是None,session会依赖全局session失效策略。
实例:
用户访问页面然后点击注销之后就把session删除掉回到主页面
views操作
def logout(request): request.session.clear() return redirect("/login.html")
urls操作
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r"^login.html$",views.login), url(r"^index.html$",views.index), url(r"^logout.html",views.logout)
前端index页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1> hello {{ username }} </h1> <a href="/logout.html">注销</a> </body> </html>
session使用二、
Django中默认支持Session,其内部提供了5种类型的Session供开发者使用:
- 数据库(默认)
- 缓存
- 文件
- 缓存+数据库
- 加密cookie
- Django默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session 表中。
- a. 配置 settings.py
• SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默认) SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)(通俗端说就是更改浏览器端session的名字) SESSION_COOKIE_PATH = "/" # Session的cookie保存的路径(默认) SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名(默认) SESSION_COOKIE_SECURE = False # 是否Https传输cookie(默认) SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http传输(默认) SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周)(默认) SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否关闭浏览器使得Session过期(默认)(设置关闭浏览器就把session失效) SESSION_SAVE_EVERY_REQUEST = False # 是否每次请求都保存Session,默认修改之后才保存(默认)(每次请求来的时候更新不更新session中的值)
b. 使用 def index(request): # 获取、设置、删除Session中数据 request.session['k1'] request.session.get('k1',None) request.session['k1'] = 123 request.session.setdefault('k1',123) # 存在则不设置 del request.session['k1'] # 所有 键、值、键值对 request.session.keys() request.session.values() request.session.items() request.session.iterkeys() request.session.itervalues() request.session.iteritems() # 用户session的随机字符串 request.session.session_key # 将所有Session失效日期小于当前日期的数据删除 request.session.clear_expired() # 检查 用户session的随机字符串 在数据库中是否 request.session.exists("session_key") # 删除当前用户的所有Session数据 request.session.delete("session_key") request.session.set_expiry(value) * 如果value是个整数,session会在些秒数后失效。 * 如果value是个datatime或timedelta,session就会在这个时间后失效。 * 如果value是0,用户关闭浏览器session就会失效。 * 如果value是None,session会依赖全局session失效策略。
2、缓存Session
a. 配置 settings.py SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 引擎 SESSION_CACHE_ALIAS = 'default' # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置 SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串 SESSION_COOKIE_PATH = "/" # Session的cookie保存的路径 SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名 SESSION_COOKIE_SECURE = False # 是否Https传输cookie SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http传输 SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周) SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否关闭浏览器使得Session过期 SESSION_SAVE_EVERY_REQUEST = False # 是否每次请求都保存Session,默认修改之后才保存 b. 使用 同上
3、文件Session
a. 配置 settings.py SESSION_ENGINE = 'django.contrib.sessions.backends.file' # 引擎 SESSION_FILE_PATH = None # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir() # 如:/var/folders/d3/j9tj0gz93dg06bmwxmhh6_xm0000gn/T SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串 SESSION_COOKIE_PATH = "/" # Session的cookie保存的路径 SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名 SESSION_COOKIE_SECURE = False # 是否Https传输cookie SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http传输 SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周) SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否关闭浏览器使得Session过期 SESSION_SAVE_EVERY_REQUEST = False # 是否每次请求都保存Session,默认修改之后才保存 b. 使用 同上
4、缓存+数据库Session
数据库用于做持久化,缓存用于提高效率 a. 配置 settings.py SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' # 引擎 b. 使用 同上
5、加密cookie Session
a. 配置 settings.py SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies' # 引擎 b. 使用 同上
基于装饰器实现用户登录
对于登录之后才能访问的功能页面,用装饰器实现
类的话是继承,方法的话就是装饰器
总体代码:
要实现如下:
1、 把数据存储在数据库中
2、 创建老师页面,登录页面,教师页面,班级页面,index公有页面
3、 通过session操作,谁登录就显示谁
from django.shortcuts import render,HttpResponse,redirect # Create your views here. from app01 import models def login(request): # models.Administrator.objects.create( # username="pyrene", # password="pyrene" # ) message='' if request.method=='POST': user=request.POST.get('user') pwd=request.POST.get('pwd') c = models.Administrator.objects.filter(username=user, password=pwd).count() if c: request.session['is_login'] = True request.session["username"]=user rep = redirect('/index.html') return rep else: message = "用户名或者密码错误" return render(request,'login.html',{"msg":message}) def logout(request): request.session.clear() return redirect("/login.html") #由于index和handler_classes都是登录后的操作所以可以用装饰器实现 def auth(func): def inner(request,*args,**kwargs): is_login = request.session.get("is_login") if is_login: return func(request,*args,**kwargs) else: return redirect("/login.html") return inner @auth def index(request): current_user=request.session.get("username") return render(request,"index.html",{"username":current_user}) @auth def handle_classes(request): current_user=request.session.get("username") return render(request,"index.html",{"username":current_user}) def handler_student(request): is_login=request.session.get("is_login") if is_login: current_user=request.session.get("username") return render(request,"student.html",{"username":current_user}) else: return redirect("/login.html") def handler_teacher(request): is_login=request.session.get("is_login") if is_login: current_user=request.session.get("username") return render(request,"teacher.html",{"username":current_user}) else: return redirect("/login.html")
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r"^login.html$",views.login), url(r"^index.html$",views.index), url(r"^logout.html",views.logout), url(r"^classes.html",views.handle_classes), url(r"^teacher.html",views.handler_teacher), url(r"^student.html",views.handler_student) # url(r"^test.html$",views.test), # url(r"^xiaohu.html$",views.xiaohu), # url(r"^js_cookie.html$",views.js_cookie) ]
from django.db import models ''' 这里创建四张表 一张班级 一张学生 一张教师,教师和班级之间的关系是多对多 一张管理员 ''' # Create your models here. class Classes(models.Model): caption=models.CharField(max_length=32) class Student(models.Model): name=models.CharField(max_length=32) cls=models.ForeignKey('Classes') class Teacher(models.Model): name=models.CharField(max_length=32) cls=models.ManyToManyField('Classes') class Administrator(models.Model): username=models.CharField(max_length=32) password=models.CharField(max_length=32)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="login.html" method="post"> {% csrf_token %} <div> <label for="user">用户名:</label> <input type="text" id="user" name="user"/> </div> <div> <label for="pwd">密 码: </label> <input type="password" name="pwd"/> </div> <div> <label></label> <input type="submit" value="登录"/> <span style="color: red">{{ msg }}</span> </div> </form> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1> hello {{ username }} </h1> <a href="/logout.html">注销</a> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>当前登录用户{{ username }}</h1> <div> </div> </body> </html>