视图
- 视图负责接受Web请求HttpRequest,进行逻辑处理,返回Web响应HttpResponse给请求者
- 视图就是一个python函数,被定义在“应用/views.py”文件中
- 响应可以是一张网页的HTML内容,一个重定向,一个404错误等
- 视图处理过程如下图:
使用视图时需要进行两方面操作,两个操作不分先后
- 配置URLconf
- 在“应用/views.py”中定义视图
URLconf
- 浏览者通过在浏览器的地址栏中输入网址请求网站,对于Django开发的网站,由哪一个视图进行处理请求,是由url匹配找到的
配置
- 在test3/settings.py中通过ROOT_URLCONF指定url配置
- 打开test3/urls.py可以看到默认配置
- 在test3/urls.py中进行包含配置,在各自应用中创建具体配置
- 定义urlpatterns列表,存储url()对象,这个名称是固定的
- urlpatterns中的每个正则表达式在第一次访问它们时被编译,这使得运行很快
语法
-
url()对象,被定义在django.conf.urls包中,有两种语法结构
-
语法一:包含,一般在自定义应用中创建一个urls.py来定义url
-
这种语法用于test3/urls.py中,目的是将应用的urls配置到应用内部,数据更清晰并且易于维护
url(正则,include(\'应用.urls\'))
- 打开test3/urls.py文件,包含booktest中的urls
url(r\'^\',include(\'booktest.urls\')),
-
在booktest目录下创建urls.py文件
- 语法二:定义,指定正则和视图的对应关系
- 在应用内部创建urls.py文件,指定请求地址与视图的对应关系
url(正则,\'视图名称\')
-
在booktest/urls.py中创建首页的url,代码如下
from django.conf.urls import url
from . import views
urlpatterns=[
url(r\'^$\',views.index),
]
-
在booktest/views.py中创建视图index
#coding=utf-8 from django.shortcuts import render from django.http import HttpResponse def index(request): return HttpResponse(\'hello world\')
- 说明1:正则部分推荐使用r,表示字符串不转义,这样在正则表达式中使用\只写一个就可以
- 说明2:不能在开始加反斜杠,推荐在结束加反斜杠
正确:index/ 正确:index 错误:/index 错误:/index/
获取值
- 请求的url被看做是一个普通的python字符串,进行匹配时不包括域名、get或post参数
- 每个捕获的参数都作为一个普通的python字符串传递给视图
- 如请求地址如下:
http://127.0.0.1:8000/1/?a=10
- 去除掉域名和参数部分后,只剩下如下部分与正则匹配
/1/
- 打开booktest/urls.py文件,定义与这个地址匹配的url如下
url(r\'^\d+/$\',views.show1),
- 在booktest/views.py中创建视图show1
def show1(request):
return HttpResponse(\'show 1\')
- 启动服务器,输入上面的网址,浏览器中效果如下图
-
获取值需要在正则表达式中使用小括号,分为两种方式注意:两种参数的方式不要混合使用,在一个正则表达式中只能使用一种参数方式
- 位置参数
- 关键字参数
方式一:位置参数
-
直接使用小括号,通过位置参数传递给视图
-
为了提取参数,修改上面的正则表达式如下
url(r\'^(\d+)/$\',views.show1),
- 修改视图show1如下
- 注意:参数的名字是任意的如a1、b8,尽量做到见名知意
def show1(request,id):
return HttpResponse(\'show %s\'%id)
- 刷新浏览器页面,效果如下图
-
在地址栏输入如下地址
http://127.0.0.1:8000/2/?a=10
- 浏览器页面效果如下图
方式二:关键字参数
-
在正则表达式部分为组命名
-
修改正则表达式如下
-
其中?P部分表示为这个参数定义的名称为id,可以是其它名称,起名做到见名知意
url(r\'^(?P<id1>\d+)/$\',views.show1),
- 修改视图show1如下
- 注意:视图show1此时必须要有一个参数名为id1,否则报错
def show1(request,id1): return HttpResponse(\'show %s\'%id1)
- 刷新浏览器页面,效果如下图
视图
-
视图就是python中的函数
-
视图一般被定义在“应用/views.py”文件中,此例中为“booktest/views.py”文件
-
视图的第一个参数必须为HttpRequest实例,还可能包含下参数如视图必须返回一个HttpResponse对象或子对象作为响应
- 通过正则表达式组获得的关键字参数
- 通过正则表达式组获取的位置参数
内置错误视图
-
Django内置处理HTTP错误的视图,主要错误及视图包括如果想看到错误视图而不是调试信息,需要修改test3/setting.py文件的DEBUG项
- 404错误:page not found视图
- 500错误:server error视图
- 400错误:bad request视图
DEBUG = False ALLOWED_HOSTS = [\'*\', ]
404错误及视图
-
将请求地址进行url检测后,没有找到匹配的正则表达式,则调用404视图,这个视图会调用404.html的模板进行渲染
-
视图传递变量request_path给模板,表示导致错误的URL
-
在templates中创建404.html
- 定义代码如下
<html>
<head>
<title></title>
</head>
<body>
找不到了
<hr/>
{{request_path}}
</body>
</html>
- 在浏览器中输入如下网址
http://127.0.0.1:8000/test/
- 运行效果如下图
500错误及视图
-
在视图中代码运行报错会发生500错误,调用内置错误视图,使用templates/500.html模板渲染
400错误及视图
-
来自客户端的安全方面非法操作会引发400错误,例如篡改会话cookie,调用内置错误视图,使用templates/400.html模板渲染
HttpReqeust对象
-
服务器接收到http协议的请求后,会根据报文创建HttpRequest对象,这个对象不需要我们创建,直接使用服务器构造好的对象使用就可以
-
视图的第一个参数必须是HttpRequest对象
-
在django.http模块中定义了HttpRequest对象的API
属性
-
下面除非特别说明,属性都是只读的
-
path:一个字符串,表示请求的页面的完整路径,不包含域名
-
method:一个字符串,表示请求使用的HTTP方法,常用值包括:\'GET\'、\'POST\'
- 在浏览器中给出地址发出请求采用get方式,如超链接
- 在浏览器中点击表单的提交按钮发起请求,如果表单的method设置为post则为post请求
-
encoding:一个字符串,表示提交的数据的编码方式GET:一个类似于字典的对象,包含get请求方式的所有参数
- 如果为None则表示使用浏览器的默认设置,一般为utf-8
- 这个属性是可写的,可以通过修改它来修改访问表单数据使用的编码,接下来对属性的任何访问将使用新的encoding值
-
POST:一个类似于字典的对象,包含post请求方式的所有参数
-
FILES:一个类似于字典的对象,包含所有的上传文件
-
COOKIES:一个标准的Python字典,包含所有的cookie,键和值都为字符串
-
session:一个既可读又可写的类似于字典的对象,表示当前的会话,只有当Django 启用会话的支持时才可用,详细内容见“状态保持”
-
运行服务器,在浏览器中浏览首页,可以在浏览器“开发者工具”中看到请求信息如下图
示例
- 接下来演示属性path、method、encoding
- 对于GET、POST、FILES、COOKIES、session后面会有详细讲解
path、encoding
- 打开booktest/views.py文件,代码如
def index(request): str=\'%s<br>%s\'%(request.path,request.encoding) return HttpResponse(str)
-
打开浏览器请求,运行效果如下图
-
以chrome浏览器为例,设置编码如下图,默认为utf-8编码
method
-
打开booktest/views.py文件,编写视图method1、method2、method3,代码如下
def method1(request):
return render(request,\'booktest/method1.html\')
def method2(request):
return HttpResponse(request.method)
def method3(request):
return HttpResponse(request.method)
-
打开booktest/urls.py文件,新增配置如下
url(r\'^method1/$\', views.method1),
url(r\'^method2/$\', views.method2),
url(r\'^method3/$\', views.method3),
- 在templates/booktest/下创建method1.html文件,代码如下
View Code
<html> <head> <title>方法练习</title> </head> <body> <a href="/method2/">方式一:get</a> <br> <br> <br> <form method="post" action="/method3/"> <input type="submit" value="方式二:post"> </form> </body> </html>
- 打开浏览器,输入如下网址
http://127.0.0.1:8000/method1/
- 浏览效果如下图
- 点击链接,转到method2,浏览效果如下图
- 回到method1页面,点击按钮,转到method3,浏览效果如下图,报错了
-
打开test3/settings.py文件,将MIDDLEWARE_CLASSES项的csrf注释
- 回到浏览器中刷新,浏览效果如下图,点击“继续”按钮
- 最终浏览效果如下图
QueryDict对象
-
定义在django.http.QueryDict
-
HttpRequest对象的属性GET、POST都是QueryDict类型的对象
-
与python字典不同,QueryDict类型的对象用来处理同一个键带有多个值的情况
-
方法get():根据键获取值
-
如果一个键同时拥有多个值将获取最后一个值
-
如果键不存在则返回None值,可以设置默认值进行后续处理
dict.get(\'键\',默认值) 可简写为 dict[\'键\']
-
方法getlist():根据键获取值,值以列表返回,可以获取指定键的所有值
-
如果键不存在则返回空列表[],可以设置默认值进行后续处理
dict.getlist(\'键\',默认值)
GET属性
- 请求格式:在请求地址结尾使用?,之后以“键=值”的格式拼接,多个键值对之间以&连接
- 例:网址如下
http://www.itcast.cn/?a=10&b=20&c=python
-
其中的请求参数为
a=10&b=20&c=python
-
分析请求参数,键为\'a\'、\'b\'、\'c\',值为\'10\'、\'20\'、\'python\'
-
在Django中可以使用HttpRequest对象的GET属性获得get方式请求的参数
-
GET属性返回QueryDict类型的对象,键和值都是字符串类型
-
键是开发人员在编写代码时确定下来的
-
值是根据数据生成的
示例
- 打开booktest/views.py文件,创建视图get1、get2、get3
# 创建链接 def get1(request): return render(request,\'booktest/get1.html\') # 接收一键一值 def get2(request): return render(request,\'booktest/get2.html\') # 接收一键多值 def get3(request): return render(request,\'booktest/get3.html\')
-
打开booktest/urls.py文件,配置url
url(r\'^get1/$\',views.get1),
url(r\'^get2/$\',views.get2),
url(r\'^get3/$\',views.get3),
-
在templates/booktest目录下创建get1.html,代码如下
<html>
<head>
<title>GET属性</title>
</head>
<body>
链接1:一个键传递一个值<br>
<a href="/get2/?a=1&b=2">get2</a>
<hr>
链接2:一个键传递多个值<br>
<a href="/get3/?a=1&a=2&b=3">get3</a>
</body>
</html>
- 运行服务器,请求get1
http://127.0.0.1:8000/get1/
-
浏览效果如下图
- 完善视图get2的代码如下
# 接收一键一值 def get2(request): dict=request.GET a=dict.get(\'a\') b=dict.get(\'b\') c=dict.get(\'c\',\'1\') context={\'a\':a,\'b\':b,\'c\':c} return render(request,\'booktest/get2.html\',context)
-
在templates/booktest目录下创建get2.html,代码如下
<html>
<head>
<title>GET属性一键一值</title>
</head>
<body>
a:{{a}}
<hr>
b:{{b}}
<hr>
c:{{c}}
</body>
</html>
- 点击链接get2,浏览效果如下图
- 完善视图get3的代码如下
# 接收一键多值 def get3(request): dict=request.GET a=dict.getlist(\'a\') b=dict.get(\'b\') context={\'a\':a,\'b\':b} return render(request,\'booktest/get3.html\',context)
- 在templates/booktest目录下创建get3.html,代码如下
<html>
<head>
<title>GET属性一键多值</title>
</head>
<body>
a:
<ul>
{%for i in a%}
<li>{{i}}</li>
{%endfor%}
</ul>
<hr>
b:{{b}}
</body>
</html>
- 后退到get1页面,点击链接get3,浏览效果如下图
POST属性
- 使用form表单请求时,method方式为post则会发起post方式的请求,需要使用HttpRequest对象的POST属性接收参数,POST属性返回QueryDict类型的对象
- 问:表单form如何提交参数呢?
- 答:控件name属性的值作为键,value属性的值为值,构成键值对提交
- 如果控件没有name属性则不提交
- 对于checkbox控件,name属性的值相同为一组,被选中的项会被提交,出现一键多值的情况
- 键是控件name属性的值,是由开发人员编写的
- 值是用户填写或选择的
示例
- 打开booktest/views.py文件,创建视图post1、post2
# 创建表单
def post1(request):
return render(request,\'booktest/post1.html\')
# 接收表单请求的数据
def post2(request):
return HttpResponse(\'hello post2\')
- 打开booktest/urls.py文件,配置url
url(r\'^post1/$\',views.post1),
url(r\'^post2/$\',views.post2),
-
在templates/booktest目录下创建post1.html,代码如下
<html>
<head>
<title>POST属性</title>
</head>
<body>
<form method="post" action="/post2/">
姓名:<input type="text" name="uname"/><br>
密码:<input type="password" name="upwd"/><br>
性别:<input type="radio" name="ugender" value="1"/>男
<input type="radio" name="ugender" value="0"/>女<br>
爱好:<input type="checkbox" name="uhobby" value="胸口碎大石"/>胸口碎大石
<input type="checkbox" name="uhobby" value="脚踩电灯炮"/>脚踩电灯炮
<input type="checkbox" name="uhobby" value="口吐火"/>口吐火<br>
<input type="submit" value="提交"/>
</form>
</body>
</html>
- 在浏览器中请求地址如下
http://127.0.0.1:8000/post1/
- 填写、选择后,浏览效果如下图
- 打开浏览器“开发者工具”,选择“Network”标签,点击“提交”按钮,在“开发者工具”中点击“post2”,找到提交数据如下图
- 完善视图post2的代码如下
# 接收表单请求的数据 def post2(request): dict=request.POST uname=dict.get(\'uname\') upwd=dict.get(\'upwd\') ugender=dict.get(\'ugender\') uhobby=dict.getlist(\'uhobby\') context={\'uname\':uname,\'upwd\':upwd,\'ugender\':ugender,\'uhobby\':uhobby} return render(request,\'booktest/post2.html\',context)
- 在templates/booktest目录下创建post2.html,代码如下
<html>
<head>
<title>POST属性</title>
</head>
<body>
用户名:{{uname}}<br>
密码:{{upwd}}<br>
性别:{{ugender}}<br>
爱好:{{uhobby}}<br>
<ul>
{%for i in uhobby%}
<li>{{i}}</li>
{%endfor%}
</ul>
</body>
</html>
- 刷新后浏览效果如下图
HttpResponse对象
-
视图在接收请求并处理后,必须返回HttpResponse对象或子对象
-
在django.http模块中定义了HttpResponse对象的API
-
HttpRequest对象由Django创建,HttpResponse对象由开发人员创建
-
运行服务器,在浏览器中浏览首页,可以在浏览器“开发者工具”中看到响应信息如下图
-
标号3为响应头信息,点击标号4处可以查看响应体信息
属性
-
content:表示返回的内容
-
charset:表示response采用的编码字符集,默认为utf-8
-
status_code:返回的HTTP响应状态码
-
content-type:指定返回数据的的MIME类型,默认为\'text/html\'
方法
-
init:创建HttpResponse对象后完成返回内容的初始化
-
set_cookie:设置Cookie信息
-
write:向响应体中写数据
-
cookie是网站以键值对格式存储在浏览器中的一段纯文本信息,用于实现用户跟踪
-
max_age是一个整数,表示在指定秒数后过期
-
expires是一个datetime或timedelta对象,会话将在这个指定的日期/时间过期
-
max_age与expires二选一
-
如果不指定过期时间,则关闭浏览器过期
-
set_cookie(key, value=\'\', max_age=None, expires=None)
delete_cookie(key):删除指定的key的Cookie,如果key不存在则什么也不发生
示例
直接返回数据
- 打开booktest/views.py文件,定义视图index2如下
def index2(request): str=\'<h1>hello world</h1>\' return HttpResponse(str)
-
打开booktest/urls.py文件,配置url
url(r\'^index2/$\',views.index2),
- 运行服务器,在浏览器中打开如下网址
http://127.0.0.1:8000/index2/
- 运行效果如下图
- 如果使用这种方式构造一个漂亮丰富的页面,对于开发人员真是会发疯,于是就有了下面的方式
调用模板
-
可以将html、css、js定义到一个html文件中,然后由视图来调用
-
打开booktest/views.py文件,定义视图index3如下
from django.template import RequestContext, loader ... def index3(request): #加载模板 t1=loader.get_template(\'booktest/index3.html\') #构造上下文 context=RequestContext(request,{\'h1\':\'hello\'}) #使用上下文渲染模板,生成字符串后返回响应对象 return HttpResponse(t1.render(context))
- 打开booktest/urls.py文件,配置url
url(r\'^index3/$\',views.index3),
- 在templates/booktest/目录下创建index3.html,代码如下
<html>
<head>
<title>使用模板</title>
</head>
<body>
<h1>{{h1}}</h1>
</body>
</html>
- 运行服务器,在浏览器中打开如下网址
http://127.0.0.1:8000/index3/
- 运行效果如下图
调用模板简写函数render
-
每次调用模板时都要执行加载、上下文、渲染三个步骤,为了简化操作,Django定义了render()函数封装了以上三个步骤的代码,定义在django.shortcuts模块中
-
打开booktest/views.py文件,定义视图index3如下
from django.shortcuts import render
...
def index3(request):
return render(request, \'booktest/index3.html\', {\'h1\': \'hello\'})
- 是不是用render()函数调用模板比上面简单多了?
子类JsonResponse
- 在浏览器中使用javascript发起ajax请求时,返回json格式的数据,此处以jquery的get()方法为例
- 类JsonResponse继承自HttpResponse对象,被定义在django.http模块中
- 接收字典作为参数
- JsonResponse对象的content-type为‘application/json’
示例
- 在booktest/views.py文件中定义视图json1、json2,代码如下
from django.http import JsonResponse ... def json1(request): return render(request,\'booktest/json1.html\') def json2(request): return JsonResponse({\'h1\':\'hello\',\'h2\':\'world\'})
- 在booktest/urls.py文件中配置url
url(r\'^json1/$\', views.json1), url(r\'^json2/$\', views.json2),
- 创建目录static/js/,把jquery文件拷贝到这个目录下
-
打开test3/settings.py文件,在文件最底部,配置静态文件查找路径,并且要求开启调试
DEBUG = True ... STATICFILES_DIRS = [ os.path.join(BASE_DIR, \'static\'), ]
- 在templates/booktest/目录下创建json1.html,代码如下
<html>
<head>
<title>json</title>
<script src="/static/js/jquery-1.12.4.min.js"></script>
<script>
$(function () {
$(\'#btnJson\').click(function () {
$.get(\'/json2/\',function (data) {
ul=$(\'#jsonList\');
ul.append(\'<li>\'+data[\'h1\']+\'</li>\')
ul.append(\'<li>\'+data[\'h2\']+\'</li>\')
})
});
});
</script>
</head>
<body>
<input type="button" id="btnJson" value="获取json数据">
<ul id="jsonList"></ul>
</body>
</html>
- 运行服务器,在浏览器中输入如下地址
http://127.0.0.1:8000/json1/
-
点击按钮“获取json数据”后浏览如下图
-
ajax代码执行过程如下
-
1.发起请求
-
2.服务器端视图执行
-
3.执行回调函数
-
子类HttpResponseRedirect
- 当一个逻辑处理完成后,不需要向客户端呈现数据,而是转回到其它页面,如添加成功、修改成功、删除成功后显示数据列表,而数据的列表视图已经开发完成,此时不需要重新编写列表的代码,而是转到这个视图就可以,此时就需要模拟一个用户请求的效果,从一个视图转到另外一个视图,就称为重定向
- Django中提供了HttpResponseRedirect对象实现重定向功能,这个类继承自HttpResponse,被定义在django.http模块中,返回的状态码为302
示例
- 在booktest/views.py文件中定义视图red1,代码如下
from django.http import HttpResponseRedirect ... # 定义重定义向视图,转向首页 def red1(request): return HttpResponseRedirect(\'/\')
- 在booktest/urls.py文件中配置url
url(r\'^red1/$\', views.red1),
- 在地址栏中输入网址如下
http://127.0.0.1:8000/red1/
- 回车后,浏览器地址栏如下图
重定向简写函数redirect
-
在django.shortcuts模块中为重定向类提供了简写函数redirect
-
修改booktest/views.py文件中red1视图,代码如下
from django.shortcuts import redirect
...
def red1(request):
return redirect(\'/\')
状态保持
-
浏览器请求服务器是无状态的。无状态指一次用户请求时,浏览器、服务器无法知道之前这个用户做过什么,每次请求都是一次新的请求。无状态的应用层面的原因是:浏览器和服务器之间的通信都遵守HTTP协议。根本原因是:浏览器与服务器是使用Socket套接字进行通信的,服务器将请求结果返回给浏览器之后,会关闭当前的Socket连接,而且服务器也会在处理页面完毕之后销毁页面对象。
-
有时需要保持下来用户浏览的状态,比如用户是否登录过,浏览过哪些商品等
-
实现状态保持主要有两种方式:
-
在客户端存储信息使用Cookie
-
在服务器端存储信息使用Session
-
Cookie
-
Cookie,有时也用其复数形式Cookies,指某些网站为了辨别用户身份、进行session跟踪而储存在用户本地终端上的数据(通常经过加密)。Cookie最早是网景公司的前雇员Lou Montulli在1993年3月的发明。Cookie是由服务器端生成,发送给User-Agent(一般是浏览器),浏览器会将Cookie的key/value保存到某个目录下的文本文件内,下次请求同一网站时就发送该Cookie给服务器(前提是浏览器设置为启用cookie)。Cookie名称和值可以由服务器端开发自己定义,这样服务器可以知道该用户是否合法用户以及是否需要重新登录等。服务器可以利用Cookies包含信息的任意性来筛选并经常性维护这些信息,以判断在HTTP传输中的状态。Cookies最典型的应用是判定注册用户是否已经登录网站,用户可能会得到提示,是否在下一次进入此网站时保留用户信息以便简化登录手续,这些都是Cookies的功用。另一个重要应用场合是“购物车”之类处理。用户可能会在一段时间内在同一家网站的不同页面中选择不同的商品,这些信息都会写入Cookies,以便在最后付款时提取信息。
-
Cookie是存储在浏览器中的一段纯文本信息,建议不要存储敏感信息如密码,因为电脑上的浏览器可能被其它人使用
-
Cookie以键值对的格式进行信息的存储
-
Cookie基于域名安全,不同域名的Cookie是不能互相访问的,如访问itcast.cn时向浏览器中写了Cookie信息,使用同一浏览器访问baidu.com时,无法访问到itcast.cn写的Cookie信息
-
当浏览器请求某网站时,会将本网站下所有Cookie信息提交给服务器
-
典型应用:记住用户名,网站的广告推送
-
说明:点击示例网址,这些广告推送的商品是基于你曾经在淘宝上点击的商品类别等条件筛选出来的,看上去这是在凤凰网上访问淘宝网的Cookie,但是事实不是这样的,一般是采用iframe标签嵌套一个淘宝的广告页面到凤凰网的页面上,所以淘宝的Cookie并没有被凤凰网读取到,而是依然交给淘宝网读取的,可以通过“开发者工具”查看元素,如下图
- 接下来讲解如何在Django中实现Cookie的读写
设置Cookie
- 打开booktest/views.py文件,创建视图cookie_set
def cookie_set(request): response = HttpResponse("<h1>设置Cookie,请查看响应报文头</h1>") response.set_cookie(\'h1\', \'hello django\') return response
- 打开booktest/urls.py文件,配置url
url(r\'^cookie_set/$\',views.cookie_set),
- 在浏览器输入如下网址
http://127.0.0.1:8000/cookie_set/
- 在“开发者工具”中可以在响应头中查看到设置的Cookie信息
读取Cookie
-
Cookie信息被包含在请求头中,使用request对象的COOKIES属性访问
-
打开booktest/views.py文件,创建视图cookie_get
def cookie_get(request): response = HttpResponse("读取Cookie,数据如下:<br>") if request.COOKIES.has_key(\'h1\'): response.write(\'<h1>\' + request.COOKIES[\'h1\'] + \'</h1>\') return response
- 打开booktest/urls.py文件,配置url
url(r\'^cookie_get/$\',views.cookie_get),
- 在浏览器输入如下网址
http://127.0.0.1:8000/cookie_get/
- 打开“开发者工具”,在请求头中可以查看Cookie信息,浏览效果如下图
Session
-
对于敏感、重要的信息,建议要储在服务器端,不能存储在浏览器中,如用户名、余额、等级、验证码等信息
-
在服务器端进行状态保持的方案就是Session
启用Session
-
Django项目默认启用Session
-
打开test3/settings.py文件,在项MIDDLEWARE_CLASSES中启用Session中间件
-
禁用Session:将Session中间件删除
存储方式
-
打开test3/settings.py文件,设置SESSION_ENGINE项指定Session数据存储的方式,可以存储在数据库、缓存、Redis等
-
存储在数据库中,如下设置可以写,也可以不写,这是默认存储方式
SESSION_ENGINE=\'django.contrib.sessions.backends.db\'
- 存储在缓存中:存储在本机内存中,如果丢失则不能找回,比数据库的方式读写更快
SESSION_ENGINE=\'django.contrib.sessions.backends.cache\'
- 混合存储:优先从本机内存中存取,如果没有则从数据库中存取
SESSION_ENGINE=\'django.contrib.sessions.backends.cached_db\'
- 如果存储在数据库中,需要在项INSTALLED_APPS中安装Session应用
- 迁移后会在数据库中创建出存储Session的表
- 表结构如下图
- 由表结构可知,操作Session包括三个数据:键,值,过期时间
依赖于Cookie
-
所有请求者的Session都会存储在服务器中,服务器如何区分请求者和Session数据的对应关系呢?
-
答:在使用Session后,会在Cookie中存储一个sessionid的数据,每次请求时浏览器都会将这个数据发给服务器,服务器在接收到sessionid后,会根据这个值找出这个请求者的Session
-
结果:如果想使用Session,浏览器必须支持Cookie,否则就无法使用Session了
-
存储Session时,键与Cookie中的sessionid相同,值是开发人员设置的键值对信息,进行了base64编码,过期时间由开发人员设置
对象及方法
-
通过HttpRequest对象的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)
示例
写
- 打开booktest/views.py文件,创建视图session_test,代码如下
def session_test(request): request.session[\'h1\']=\'hello\' return HttpResponse(\'写session\')
- 打开booktest/urls.py文件,配置url
url(r\'^session_test/$\',views.session_test),
- 运行服务器,打开浏览器请求如下网址
http://127.0.0.1:8000/session_test/
- 浏览效果如下图,在“开发者工具”中可以查看到响应头中创建了Cookie,里面有个键为sessionid
- 打开MySQL数据库命令行,查询数据如下图
-
查看Cookie中的sessionid值为“l48euizwnd0u1vrq401rwc9yqxkj4ip4”,数据表中session的键为“l48euizwnd0u1vrq401rwc9yqxkj4ip4”,是一样的,这样,服务器就可以在众多的请求者中找到对应的Session数据
-
在MySQL数据库命令行中复制值,在Base64解码中进行解码查看如下图
读
- 打开booktest/views.py文件,修改session_test视图如下
def session_test(request): # request.session[\'h1\']=\'hello\' h1=request.session.get(\'h1\') return HttpResponse(h1)
- 刷新浏览器效果如下图
删键
-
打开booktest/views.py文件,修改session_test视图如下
def session_test(request): # request.session[\'h1\']=\'hello\' # h1=request.session.get(\'h1\') del request.session[\'h1\'] return HttpResponse(\'ok\')
- 刷新浏览器,在数据库命令行中查询,base64解码后如下图
- 如果将所有的键及值都删除,逐个调用del太麻烦,可以使用clear()方法
删会话
- 打开booktest/views.py文件,修改session_test视图如下
def session_test(request): # request.session[\'h1\']=\'hello\' # h1=request.session.get(\'h1\') # del request.session[\'h1\'] request.session.flush() return HttpResponse(\'ok\')
- 刷新浏览器,在数据库命令行中查询如下图
使用Redis存储Session
-
会话还支持文件、纯cookie、Memcached、Redis等方式存储,下面演示使用redis存储
-
安装包
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\'
- 打开booktest/views.py文件,修改session_test视图如下
def session_test(request): request.session[\'h1\']=\'hello\' # h1=request.session.get(\'h1\') # del request.session[\'h1\'] # request.session.flush() return HttpResponse(\'ok\')
- 管理redis的命令,需要保证redis服务被开启
查看:ps ajx|grep redis 启动:sudo service redis start 停止:sudo service redis stop 使用客户端连接服务器:redis-cli 切换数据库:select 2 查看所有的键:keys * 获取指定键的值:get name
- 刷新浏览器,在redis客户端中查看数据如下图
总结
- 配置URLconf
- 定义视图
- HtpRequest对象及GET、POST属性
- HttpReponse对象、JsonResponse对象、HttpResponseRedirect对象及简写函数
- 状态保持Cookie、Session