Django(5) session登录注销、csrf及中间件自定义、django Form表单验证(非常好用)
一、Django中默认支持Session,其内部提供了5种类型的Session供开发者使用:
- 数据库(默认)
- 缓存
- 文件
- 缓存+数据库
- 加密cookie
1、数据库Session
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
Django默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session 表中。a. 配置 settings.py SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默认) 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 #为True时,不再点击页面后,相应时间后session失效,为False,第一次点击后, 相应时间后失效 是否每次请求都保存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
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
a. 配置 settings.py 修改SESSION_ENGINE
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 = True # 是否每次请求都保存Session,默认修改之后才保存b. 使用 同上 |
3、文件Session
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
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
|
1
2
3
4
5
6
7
8
9
|
数据库用于做持久化,缓存用于提高效率a. 配置 settings.py SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' # 引擎b. 使用 同上 |
5、加密cookie Session
|
1
2
3
4
5
6
7
|
a. 配置 settings.py SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies' # 引擎b. 使用 同上 |
二、session应用示例:用户登录验证与用户注销
urls.py
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/$', views.login),
url(r'^index/$', views.index),
url(r'^logout/$', views.logout),
]
views.py
from django.shortcuts import render,redirect,HttpResponse
def login(request):
if request.method == "GET":
return render(request,'login.html')
elif request.method == "POST":
user = request.POST.get('user')
pwd = request.POST.get('pwd')
if user == 'root' and pwd == "123":如果验证成功,则
# session中设置值,其中session是一个字典
request.session['username'] = user
request.session['is_login'] = True#设置是否登录标记
if request.POST.get('rmb',None) == '1':#判断界面是否选择10秒免登陆,如果是10秒免登陆,则设置超时时间为10秒
#即10秒后需重新登录
request.session.set_expiry(10)# 超时时间为10秒
return redirect('/index/')
else:
return render(request,'login.html')
def index(request):
#获取session中的值
if request.session.get('is_login',None):#如果能获取到已经登录标记,则跳转到数据显示界面
return render(request,'index.html',{'username': request.session['username']})
else:#否则跳转到错误界面
return HttpResponse('gun')
def logout(request):#注销,清除session即可
# del request.session['username'] 清除某一个用户的session
request.session.clear() #清空所有的session
return redirect('/login/')
login.html
<body>
<form action="/login/" method="POST">
{% csrf_token %}
<input type="text" name="user" />
<input type="text" name="pwd" />
<input type="checkbox" name="rmb" value="1" /> 10秒免登录
<input type="submit" value="提交" />
</form>
</body>
三、在不注释settings.py中的csrf时,要用ajax提交的话,必须在提交前用 $.ajaxSetup
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<form action="/login/" method="POST">
{% csrf_token %}
<input type="text" name="user" />
<input type="text" name="pwd" />
<input type="checkbox" name="rmb" value="1" /> 10秒免登录
<input type="submit" value="提交" />
<input id="btn1" type="button" value="按钮1" />
<input id="btn2" type="button" value="按钮2" />
</form>
<script src="/static/jquery-1.12.4.js"></script>
<script src="/static/jquery.cookie.js"></script>
<script>
$(function(){
//在不注释settings.py中的csrf时,要用ajax提交,必须在提交前用下边的$.ajaxSetup,这样无论下边有多少ajax操作,
//只写这一个$.ajaxSetup即可
$.ajaxSetup({
beforeSend: function(xhr,settings){ //括号里的都是固定格式
xhr.setRequestHeader('X-CSRFtoken', $.cookie('csrftoken')); //固定格式,设置csrftoken
}
});
$('#btn1').click(function () {
$.ajax({
url: '/login/',
type:"GET",
data: {'user': 'root', 'pwd': '123'},
// headers: {'X-CSRFtoken': $.cookie('csrftoken')},
success:function(arg){
}
})
});
})
</script>
</body>
</html>
views.py 同二
urls.py 同二
四、Django中间件
settings.py
MIDDLEWARE = [
# 'django.middleware.cache.UpdateCacheMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'Middle.m1.Row1',#写上自定义中间件函数的路径,.为分隔符
'Middle.m1.Row2',
'Middle.m1.Row3',
]
自定义中间件函数(自己创建一个目录:项目/Middle/m1.py)
m1.py
from django.utils.deprecation import MiddlewareMixin
class Row1(MiddlewareMixin):#自定义中间件
def process_request(self,request): #注意,中间件的函数名必须为process_request、process_view、process_response,而且process_request
#不能有返回值,如果有返回值,请求就不继续往下一个中间件走了,就会沿着已经走过的中间件的
# process_response返回 #正常情况下,数据流程:数据先到Row1的process_request,再到Row2的process_request,再到Row1的process_view, #再到Row2的process_view,再到Row2的process_response、再到Row1的process_response,最后再执行view.py中 #的函数。
print('王森')
def process_view(self, request, view_func, view_func_args, view_func_kwargs):
print('张欣彤')
def process_response(self, request, response):
print('扛把子')
return response
from django.shortcuts import HttpResponse
class Row2(MiddlewareMixin):
def process_request(self,request):
print('程毅强')
# return HttpResponse('走')
def process_view(self, request, view_func, view_func_args, view_func_kwargs):
print('张需要')
def process_response(self, request, response):
print('侯雅凡')
return response
class Row3(MiddlewareMixin):
def process_request(self,request):
print('刘东')
def process_view(self, request, view_func, view_func_args, view_func_kwargs):
print('邵林')
def process_response(self, request, response):
print('连之泪')
return response
def process_exception(self, request, exception):
if isinstance(exception,ValueError):
return HttpResponse('出现异常》。。')
def process_template_response(self,request,response):
# 如果Views中的函数返回的对象中,具有render方法
print('-----------------------')
return response
五、django Form表单验证
1.最基本的Form表单验证及错误信息返回
views.py
from django import forms
from django.forms import widgets
from django.forms import fields
from django.shortcuts import render
from app01 import models
class FM(forms.Form):
# 字段本身只做验证
user = fields.CharField(
error_messages={'required': '用户名不能为空.'},#自定义错误信息
label="用户名",
)
pwd = fields.CharField(
max_length=12, #指定密码长度最大为12
min_length=6, #指定密码长度最小为6
error_messages={'required': '密码不能为空.', 'min_length': '密码长度不能小于6', "max_length": '密码长度不能大于12'},
)
email = fields.EmailField(error_messages={'required': '邮箱不能为空.','invalid':"邮箱格式错误"})
def fm(request):
if request.method == "GET":
obj = FM()#实例化自定义表单
return render(request,'fm.html',{'obj': obj})#这里将obj传给前端,实际上是将html标签传到前端,前端不用再写html标签
elif request.method == "POST":
# 获取用户所有数据
# 每条数据请求的验证
# 成功:获取所有的正确的信息
# 失败:显示错误信息
obj = FM(request.POST)#获取以post方式提交的数据,包含正确和错误信息
r1 = obj.is_valid()#如果正确获得全部数据,则返回true,否则返回false
if r1:
# obj.cleaned_data 获取到前端输入数据,形式是字典形式
models.UserInf.objects.create(**obj.cleaned_data) #直接将获取到的字典数据写到数据库里即可
else:
# obj.errors继承自字典ErrorDict
# print(obj.errors.as_json()) 以json形式获取数据,得到字典数据
# print(obj.errors['user'][0]) 获取到用户名 的第一个错误信息
return render(request,'fm.html', {'obj': obj})#这里将错误信息传到前端
return render(request,'fm.html')
fm.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<form action="/fm/" method="POST">
{% csrf_token %}
<p> {{ obj.user }} {{ obj.errors.user.0 }}</p> //{{ obj.user }}是输入用户名的标签;{{ obj.errors.user.0 }}是要显示的错误信息
<p>{{ obj.pwd }} {{ obj.errors.pwd.0 }}</p>
<p>{{ obj.email }}{{ obj.errors.email.0 }}</p>
<input type="submit" value="提交" />
</form>
</body>
</html>
2.完整Form表单验证实例
views.py
from django import forms
from django.forms import widgets
from django.forms import fields
class FM(forms.Form):
# 字段本身只做验证
user = fields.CharField( #字段:自定义输入框要用fields
error_messages={'required': '用户名不能为空.'},
label="用户名",#自定义前端标签名
widget=widgets.Textarea(attrs={'class': 'c1'}),#插件:自定义输入框的样式要用widget
)
pwd = fields.CharField(
max_length=12,
min_length=6,
error_messages={'required': '密码不能为空.', 'min_length': '密码长度不能小于6', "max_length": '密码长度不能大于12'},
widget=widgets.PasswordInput(attrs={'class': 'c2'})#插件:自定义输入框的样式
)
email = fields.EmailField(error_messages={'required': '邮箱不能为空.','invalid':"邮箱格式错误"})
f = fields.FileField()#上传文件,在下边的fm函数获取文件时,f就是字典的key
# p = fields.FilePathField(path='app01') #显示出app01目录下的所有文件路径,注意是路径
city1 = fields.ChoiceField( #显示select下拉框
choices=[(0,'上海'),(1,'广州'),(2,'东莞')]
)
city2 = fields.MultipleChoiceField( #显示select多选框
choices=[(0,'上海'),(1,'广州'),(2,'东莞')]
)
from app01 import models
def fm(request):
if request.method == "GET":
# 从数据库中把数据获取到所需要的数据
dic = {#给各个字段设置默认值(也可以用于在页面做编辑或添加操作时,显示默认值)
"user": 'r1',
',
'email': 'sdfsd',
'city1': 1,
'city2': [1,2]
}
obj = FM(initial=dic)#给各个字段设置默认值
return render(request,'fm.html',{'obj': obj})
elif request.method == "POST":
# 获取用户所有数据
# 每条数据请求的验证
# 成功:获取所有的正确的信息
# 失败:显示错误信息
obj = FM(request.POST)
r1 = obj.is_valid()
if r1:
# obj.cleaned_data
models.UserInf.objects.create(**obj.cleaned_data)
else:
# ErrorDict
# print(obj.errors.as_json())
# print(obj.errors['user'][0])
return render(request,'fm.html', {'obj': obj})
return render(request,'fm.html')
fm.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<form action="/fm/" method="POST">
{% csrf_token %}#中间件插件
<p>{{ obj.user.label }} {{ obj.user }} {{ obj.errors.user.0 }}</p>
#{{ obj.user.label }}显示标签名 {{ obj.user }}显示输入框 {{ obj.errors.user.0 }}显示错误信息
<p>{{ obj.pwd }} {{ obj.errors.pwd.0 }}</p>
<p>{{ obj.email }}{{ obj.errors.email.0 }}</p>
<p>{{ obj.f }}{{ obj.errors.f.0 }}</p> #显示上传文件选择框
<p>{{ obj.p }}{{ obj.errors.p.0 }}</p> #以下拉框的形式,显示app01目录下的所有文件的路径
{{ obj.city1 }} #显示select下拉框
{{ obj.city2 }} #显示select多选框
<input type="submit" value="提交" />
</form>
</body>
</html>
附加:从数据库取choice选项
在使用选择标签时,需要注意choices的选项可以从数据库中获取,但是由于是静态字段 ***当数据库数据发生变化时,无法实时获取最新数据***,那么需要自定义构造方法从而达到此目的。
方式一:
from django.forms import Form
from django.forms import widgets
from django.forms import fields
from django.core.validators import RegexValidator
class MyForm(Form):
user = fields.ChoiceField(#创建一个输入用户名的user框
# choices=((1, '上海'), (2, '北京'),),
initial=2,
widget=widgets.Select(choices=[])
)
def __init__(self, *args, **kwargs):
super(MyForm,self).__init__(*args, **kwargs)
self.fields['user'].widget.choices = models.Classes.objects.all().value_list('id','caption')
3.常用的Form表单字段及其用法(视频22天--19、20)
自定义widget样式要用attr参数: widget=widgets.Textarea(attrs={'class': 'c1'}),
Django(5) session登录注销、csrf及中间件自定义、django Form表单验证(非常好用)的更多相关文章
- Day19 Django之Form表单验证、CSRF、Cookie、Session和Model操作
一.Form表单验证 用于做用户提交数据的验证1.自定义规则 a.自定义规则(类,字段名==html中的name值)b.数据提交-规则进行匹配代码如下: """day19 ...
- python_way day19 HTML-day5 (form表单验证,CSRF,cookie,session,缓存)
python-way day19 1. dJango的form表单验证 2.CSRF 跨站请求伪造 3.cookie,session 4.缓存 一,django表单验证功能 1.django验证基础: ...
- web框架-(六)Django补充---form表单验证
一.form表单验证 1. 常规html页面的form表单验证 常规页面中,如果想实现对表单中用户输入信息的数据验证,需要配合Ajax来实现. 使用前我们先来熟悉下函数参数:request,其中包含的 ...
- django之form表单验证
django中的Form一般有两种功能: 输入html 验证用户输入 #!/usr/bin/env python # -*- coding:utf- -*- import re from django ...
- django form表单验证
一. django form表单验证引入 有时时候我们需要使用get,post,put等方式在前台HTML页面提交一些数据到后台处理例 ; <!DOCTYPE html> <html ...
- 6.4-6.5 使用form表单验证,完善登录页面
之前是使用自定义的类来实现登录逻辑,现在使用django内置的form表单验证,用继承django的view来实现登录页面. users > views.py 的内容是: from django ...
- Django中的Form表单验证
回忆一下Form表单验证的逻辑: 前端有若干个input输入框,将用户输入内容,以字典传递给后端. 后端预先存在一个Form表单验证的基类,封装了一个检测用户输入是否全部通过的方法.该方法会先定义好错 ...
- 第三百一十一节,Django框架,Form表单验证
第三百一十一节,Django框架,Form表单验证 表单提交 html <!DOCTYPE html> <html lang="en"> <head& ...
- Django基础之Form表单验证
Form表单验证 1.创建Form类(本质就是正则表达式的集合) from django.forms import Form from django.forms import fields from ...
随机推荐
- 一个div添加多个背景图片
效果图如下:
- CSS探案之 background背景属性剖析
首先,我们先来看看两个css属性:background和background-color,对!就是这两位,相信大家在平时应该没少 麻烦人家把,反正我是这样,几乎也少会用到背景图,原因很简单:就是有点害 ...
- centos7 docker 安装 mysql5.7.24 导入12G的sql
先在CentOS7里面安装docker Docker 要求 CentOS 系统的内核版本高于 3.10 ,查看本页面的前提条件来验证你的CentOS 版本是否支持 Docker .通过 uname - ...
- 修改stl::set相关源码,提供有序属性值的查找接口
普通的stl::set,查找时只能传入key_type. 不能使用属性值查找. 例如: /* an employee record holds its ID, name and age */ clas ...
- 190221协程与IO模型
一.协程 又称微线程 协程是一种用户态的轻量级的线程 在单线程下实现的并发,例如:yield 优点: 无需线程上下文切换的开销 无需原子操作锁定及同步的开销 方便切换控制流,简化编程模型 高并发,高扩 ...
- XAF对Attribute的总结
[Aggregated] 没有参数,作用于a property or a field,并且只能是持久类的引用或者XPCollection.实现两个持久类的级联删除的功能. [Association(& ...
- tornado 07 数据库—ORM—SQLAlchemy—查询
tornado 07 数据库—ORM—SQLAlchemy—查询 引言 #上节课使用query从数据库查询到了结果,但是query返回的对象是直接可用的吗 #在query.py内输入一下内容 from ...
- LCT小小结
模板题P3690 基础题P3203[HNOI2010]弹飞绵羊 \(access\)是搞出一条端点为\(x,y\)的路径 , 且维护的是实子树的信息 . 由于题目比较简单 , \(access\)时还 ...
- 51Nod-1259-整数划分 V2
51Nod-1259-整数划分 V2 将N分为若干个整数的和,有多少种不同的划分方式,例如:n = 4,{4} {1,3} {2,2} {1,1,2} {1,1,1,1},共5种.由于数据较大,输出M ...
- POJ_1703 Find them, Catch them 【并查集】
一.题面 POJ1703 二.分析 需要将并查集与矢量法则相结合.par数组用以记录父节点,rank用以记录与父节点的关系.如题意,有两种关系,设定0是属于同一个帮派,1表示不属于同一个帮派. 运用并 ...