Form表单

常规html页面的form表单验证

常规页面中,如果想实现对表单中用户输入信息的数据验证,需要配合Ajax来实现.

使用前我们先来熟悉下函数参数:request,其中包含的意义:

request.path               除去了域名和端口的访问路径,
request.get_host 域名+端口信息
request.get_full_path() 所有路径,包含传递的参数
requets.is_secure() 是否使用https进行链接

Django中的form库:每一个邦定Form实体都有一个errors属性,它为你提供了一个字段与错误消息相映射的字典表。可以这么定义:

>>> f = ContactForm({'subject': 'Hello', 'message': ''})
>>> f.errors
{'message': [u'This field is required.']}

实现验证的必要条件:

  1. 在views.py中定义一个继承了父类forms.Form的子类
  2. 在页面中需要设置name属性
  3. 后台验证时使用LoginForm(request.POST)获取表单确认结果
  4. 获取结果后,使用LoginForm(request.POST).is_valid()判断是否有误(True为无错误,False为有错误)
  5. 用户页面提交时,需要将输入内容拼接为字典形式,并且属性name的值要与views.py 中定义的一致

下面我们看下代码吧:

views.py代码:

class LoginForm(forms.Form):
user = forms.CharField(required=True, error_messages={'required': '用户名不能为空.'})
pwd = forms.CharField(required=True,
min_length=6,
max_length=10,
error_messages={'required': '密码不能为空.', 'min_length': "至少6位"}) num = forms.IntegerField(error_messages={'required': '数字不能空.', 'invalid': '必须输入数字'}) phone = forms.CharField(validators=[mobile_validate, ], ) def login1(request):
if request.method == 'POST':
result = {'status': False, 'message': None}
obj = LoginForm(request.POST)
ret = obj.is_valid()
if ret:
print(obj.clean())
result['status'] = True
else:
from django.forms.utils import ErrorDict
print(type(obj.errors), obj.errors.as_json())
# print(obj.errors)
error_str = obj.errors.as_json()
result['message'] = json.loads(error_str)
return HttpResponse(json.dumps(result))
return render(request, 'login1.html')

login1.html页面:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
.error_msg{
color: red;
}
</style>
</head>
<body>
<div>
<div>
<input type="text" name="user" />
</div>
<div>
<input type="password" name="pwd" />
</div>
<input type="button" value="提交" onclick="DoSubmit();" />
</div>
<script src="/static/jquery-1.12.4.js"></script>
<script> function DoSubmit(){
$('.error_msg').remove();
var input_dict = {};
$('input').each(function(){
var v = $(this).val();
var n = $(this).attr('name');
input_dict[n] = v;
});
console.log(input_dict);
$.ajax({
url: '/login1/',
type: 'POST',
data: input_dict,
dataType:'json',
success: function (result) {
if(result.status){
location.href = '/index/'
}else {
$.each(result.message,function (k,v) {
console.log(k,v[0].message);
var tag = document.createElement('span');
tag.className = 'error_msg';
tag.innerText = v[0].message;
$('input[name="'+k +'"]').after(tag); }) } }
})
}
</script>
</body>
</html>

怎么样,比较复杂吧,为什么复杂,我们要自己创建便签,自己生成HTML页面,很麻烦,那么我们就来看下django自带的form库!

Django自带form进行验证

权威django讲解form的地址:http://www.kancloud.cn/thinkphp/django-book/39587

Django中的form一般自带两个功能

  • 自动生产HTML
  • 验证用户输入

详细参数地址

views.py设置:

def mobile_validate(value):
mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')
if not mobile_re.match(value):
raise ValidationError('手机号码格式错误') class LoginForm(forms.Form):
user = forms.CharField(required=True, error_messages={'required': '用户名不能为空.'})
pwd = forms.CharField(required=True,
min_length=6,
max_length=10,
error_messages={'required': '密码不能为空.', 'min_length': "至少6位"}) num = forms.IntegerField(error_messages={'required': '数字不能空.', 'invalid': '必须输入数字'}) phone = forms.CharField(validators=[mobile_validate, ], )
topic = forms.ChoiceField(choices=TOPIC_CHOICES,label='选择评分') ###页面处理 def login(request):
if request.POST:
objPost = LoginForm(request.POST)
ret = objPost.is_valid()
if ret:
print(objPost.clean())
else:
from django.forms.utils import ErrorDict
# print(type(obj.errors),obj.errors.as_json())
# obj1.errors
pass
return render(request, 'login.html', {'obj1': objPost})
else:
objGet = LoginForm()
return render(request, 'login.html', {'obj1': objGet})

其中error_messages定义了出错时显示在页面的错误消息

此处的topic中的choices需要在models.py中定义一个数组.

TOPIC_CHOICES = (
('leve1', '差评'),
('leve2', '中评'),
('leve3', '好评'),
)

html的页面中就很简单了,我们来看下:

login.html:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<style>
.error_msg{
color: red;
}
</style>
</head>
<body>
<form action="/login/" method="POST">
<div>
{{ obj1.user }}
{% if obj1.errors.user %}
<span class="error_msg">{{ obj1.errors.user.0 }}</span>
{% endif %}
</div>
<div>
{{ obj1.pwd }}
{% if obj1.errors.pwd %}
<span class="error_msg">{{ obj1.errors.pwd.0 }}</span>
{% endif %}
</div>
<div>
{{ obj1.num }}
{% if obj1.errors.num %}
<span class="error_msg">{{ obj1.errors.num.0 }}</span>
{% endif %}
</div>
<div>
{{ obj1.phone }}
{% if obj1.errors.phone %}
<span class="error_msg">{{ obj1.errors.phone.0 }}</span>
{% endif %}
</div>
<input type="submit" value="提交"/> </form> </body>
</html>

代码很少就能完美解决,真方便...

自定义form验证机制

关于自定义Form验证机制,可以看一下这个:http://www.cnblogs.com/ccorz/p/5868380.html

跨站请求csrf

概述

django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成。而对于django中设置防跨站请求伪造功能有分为全局和局部。

  1. 全局:文件位置setting.py,文件中间件位置:django.middleware.csrf.CsrfViewMiddleware
  2. 局部:
    • @csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。

    • @csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。

    • 注意:以上需要导入模块:from django.views.decorators.csrf import csrf_exempt,csrf_protect

应用

使用时,views.py中无需设置任何东西,常规return render(xxx)即可,主要是在HTML页面中.

普通表单

普通form中添加在form中设置{% csrf_token %}即可.如下:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>csrf</title>
</head>
<body>
<form action="/csrf/" method="POST">
{% csrf_token %}
<input type="text" name="v"/>
<input type="submit" value="提交"/>
</form> </body>
</html>

Ajax

对于传统的form,可以通过表单的方式将token再次发送到服务端,而对于ajax的话,使用如下方式。

需要在script部分写入如下内容:

var csrftoken = $.cookie('csrftoken');

function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});

我们可以将以上代码写入一个js文件,然后在使用时导入script.

html如下:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>csrf</title>
</head>
<body>
<input type="button" value="ajax提交" onclick="doajax();" /> <script src="/static/jquery-1.12.4.js"></script>
<script src="/static/jquery.cookie.js"></script>
<script src="/static/csrf.js"></script>
<script>
{# var csrftoken = $.cookie('csrftoken');#}
{##}
{# function csrfSafeMethod(method) {#}
{# // these HTTP methods do not require CSRF protection#}
{# return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));#}
{# }#}
{# $.ajaxSetup({#}
{# beforeSend: function(xhr, settings) {#}
{# if (!csrfSafeMethod(settings.type) && !this.crossDomain) {#}
{# xhr.setRequestHeader("X-CSRFToken", csrftoken);#}
{# }#}
{# }#}
{# });#} function doajax() {
$.ajax({
url:'/csrf/',
type:'POST',
data:{'k1':'v1'},
success:function (data) {
console.log(data) }
}) } </script>
</body>
</html>

cookie

获取cookie

request.COOKIES['key']
request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
参数:
default: 默认值
salt: 加密盐
max_age: 后台控制过期时间

设置Cookie

rep = HttpResponse(...) 或 rep = render(request, ...)

rep.set_cookie(key,value,...)
rep.set_signed_cookie(key,value,salt='加密盐',...)
参数:
key, 键
value='', 值
max_age=None, 超时时间
expires=None, 超时时间(IE requires expires, so set it if hasn't been already.)
path='/', Cookie生效的路径,/ 表示根路径,特殊的:跟路径的cookie可以被任何url的页面访问
domain=None, Cookie生效的域名
secure=False, https传输
httponly=False 只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)

前端操作cookie

由于cookie保存在客户端的电脑上,所以,JavaScript和jquery也可以操作cookie。

<script src='/static/js/jquery.cookie.js'></script>
$.cookie("list_pager_num", 30,{ path: '/' });

session

session一般是与cookie配合一起使用的,否则没有cookie的session没有什么实际意义.

Django中默认支持Session,其内部提供了5种类型的Session供开发者使用:

  • 数据库(默认)
  • 缓存
  • 文件
  • 缓存+数据库
  • 加密cookie

数据库session

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 # 是否每次请求都保存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") ...

缓存session

配置 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,默认修改之后才保存

文件session

配置 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,默认修改之后才保存

缓存+数据库session

数据库用于做持久化,缓存用于提高效率

配置 settings.py

    SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'        # 引擎

加密cookie session

配置 settings.py

    SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'   # 引擎

使用方式都一样.

扩展:session用户验证

def session_login(request):
if request.method == 'POST':
u = request.POST.get('user', None)
p = request.POST.get('pwd', None)
if p == '123' and u in USER_LIST:
request.session['user'] = u
return redirect('/session_index/')
return render(request, 'session_login.html')

session 实例:用户登录退出

分析需求,一共三个页面,登录、登录后提示成功页面、以及注销页面.

views.py设置:

USER_LIST = ['alex', 'hu', 'eric', 'cc']

#设置装饰器
def check_login(func):
def inner(request, *args, **kwargs):
user = request.session.get('user')
if not user:
return redirect('/session_login')
return func(request, *args, **kwargs) return inner #设置登录页面后台处理
def session_login(request):
if request.method == 'POST':
u = request.POST.get('user', None)
p = request.POST.get('pwd', None)
if p == '123' and u in USER_LIST:
request.session['user'] = u
return redirect('/session_index/')
return render(request, 'session_login.html') #登录后的提示页面
@check_login
def session_index(request):
user = request.session.get('user', None)
return render(request, 'session_index.html', {'user': user}) #注销后台处理
@check_login
def session_logout(request):
del request.session['user']
return redirect('/session_login/')

登录页面:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<form action="/session_login/" method="POST">
<input type="text" name="user">
<input type="text" name="pwd">
<input type="submit" value="提交" />
</form>
</body>
</html>

登录后的跳转首页:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<h1>欢迎:{{ user }}登录</h1> <a href="/session_logout/">注销</a>
</body>
</html>

Django之Form、跨站请求以及cookie、session的更多相关文章

  1. Django之CSRF 跨站请求伪造

    一.简介 1.点我了解什么是跨站请求伪造 2.django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成.而对 ...

  2. Django框架之跨站请求伪造

    跨站请求伪造(英语:Cross-site request forgery),也被称为one-click attack或者session riding,通常缩写为CSRF或者XSRF, 是一种挟制用户在 ...

  3. Django之cfrs跨站请求伪造和xfs攻击

    跨站请求伪造 一.简介 django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成.而对于django中设置防 ...

  4. django的csrf跨站请求伪造

    1.什么是跨站请求伪造 请看图: 我们自行写了一个网站模仿中国银行,用户不知道是否是真的中国银行,并且提交了转账信息,生成一个form表单,向银行服务器发送转账请求,这个form表单和正规银行网站的f ...

  5. Django添加防跨站请求伪造中间件

    第一步: 在全局设置中打开此中间件: MIDDLEWARE_CLASSES = [ ... 'django.middleware.csrf.CsrfViewMiddleware', ... ]     ...

  6. django CBV装饰器 自定义django中间件 csrf跨站请求伪造 auth认证模块

    CBV加装饰器 第一种 @method_decorator(装饰器) 加在get上 第二种 @method_decorator(login_auth,name='get') 加在类上 第三种 @met ...

  7. Django之CSRF跨站请求伪造(老掉牙的钓鱼网站模拟)

    首先这是一个测试的代码 请先在setting页面进行下面操作 注释完成后,开始模拟钓鱼网站的跨站请求伪造操作: 前端代码: <!DOCTYPE html> <html lang=&q ...

  8. django中csrftoken跨站请求伪造的几种方式

    1.介绍 我们之前从前端给后端发送数据的时候,一直都是把setting中中间件里的的csrftoken这条给注释掉,其实这个主要起了一个对保护作用,以免恶意性数据的攻击.但是这样直接注释掉并不是理智型 ...

  9. Web框架之Django_09 重要组件(Django中间件、csrf跨站请求伪造)

    摘要 Django中间件 csrf跨站请求伪造 一.Django中间件: 什么是中间件? 官方的说法:中间件是一个用来处理Django的请求和响应的框架级别的钩子.它是一个轻量.低级别的插件系统,用于 ...

随机推荐

  1. 系统间HTTP调用代码封装

    痛点 最近接手一个老项目,这个项目几经转手,到我这里时,发现代码的可阅读性实在是很差,对于一个有点代码洁癖的我来说,阅读起来实在是很难受.其中一个痛点,现在就拉出来讲讲.该项目需要与另外一个项目进行业 ...

  2. JS多线程之Web Worker

    什么是Web Worker web worker 是运行在后台的 JavaScript,不会影响页面的性能. 当在 HTML 页面中执行脚本时,页面的状态是不可响应的,直到脚本已完成. web wor ...

  3. EntityFramework 事物引发的问题

    前记 还是最近做的日志模块,今天做最后的入库工作.在测试入库日志记录时,总是出现怪异的问题. 开启服务开始接收 Kafka 的消息,第一条数据没有问题,后面的都如不了库.很是懵~~~ 调试了很久定位在 ...

  4. sql 索引的使用 转载:https://www.cnblogs.com/xiaoyangjia/p/11267191.html#mysql_performance

    B-Tree索引的3个限制: 如果不是按照索引的最左列开始查找,则无法使用索引 不能跳过索引中的列.如果联合索引(a,b,c) ,如果使用条件a和c条件查询,那么只能使用索引的第一列a 如果查询中有某 ...

  5. python 单引号与双引号的转义

    import simplejson a = """{"a":"\\""}""" b = & ...

  6. 理解git 中的HEAD指针&branch指针

    理解git 中的HEAD指针&branch指针 Yooye关注 2019.02.28 10:44:32字数 492阅读 668 HEAD指针 使用git checkout 来移动HEAD指针, ...

  7. dumpe/dumpe2fs/e2fsck

    xt2/3/4文件系统备份工具 导出ext2/ext3/ext4文件系统信息 dumpe2fs e2fsck 强制检查文件系统 检查文件系统

  8. jQuery相关方法3----动画相关

    一.显示和隐藏 show(参数1,参数2)方法和hide(参数1,参数2)方法,动画效果显示和隐藏 参数1是时间,单位毫秒(1000毫秒=1秒),也可以是 "slow"" ...

  9. 【算法】变邻域搜索算法(Variable Neighborhood Search,VNS)超详细一看就懂的解析

    更多精彩尽在微信公众号[程序猿声] 变邻域搜索算法(Variable Neighborhood Search,VNS)一看就懂的解析 00 目录 局部搜索再次科普 变邻域搜索 造轮子写代码 01 局部 ...

  10. TensorFlow(十八):从零开始训练图片分类模型

    (一):进入GitHub下载模型-->下载地址 因为我们需要slim模块,所以将包中的slim文件夹复制出来使用. (1):在slim中新建images文件夹存放图片集 (2):新建model文 ...