Django框架8
Django框架8
forms组件
实现一个小需求:
我们写一个注册页面,获取用户输入的用户民和密码
用户点击注册发送到后端做用户名密码的校验
用户名不可包括尼玛 包含敏感词汇
密码不能为空 密码怎么可以为空
用form表单来实现,提交一次,刷新一次,清空输入框一次
前端代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
<link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<form action="" method="post">
<p>
用户名:<input type="text" name="username">
<span style="color: red">{{ error_dict.username }}</span>
</p>
<p>密码:<input type="text" name="password">
<span style="color: red">{{ error_dict.password }}</span>
</p>
<p><input type="submit"></p>
</form>
</body>
</html>
后端代码
def register(request):
error_dict = {}
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
if '尼玛' in username:
error_dict['username'] = '不可包含敏感词汇'
if not password:
error_dict['password'] = '密码怎么可以为空'
return render(request, 'register.html', locals())
forms组件
1.渲染页面 手写获取用户输入的前端页面代码
2.校验数据 后端获取用户数据并做合法性校验
3.展示信息 将校验之后的结果渲染到前端页面
先创建一个类
from django import forms
class MyRegForm(forms.Form):
# 用户名最少3位最多六位
username = forms.CharField(max_length=8, min_length=3)
password = forms.CharField(max_length=8, min_length=3)
# email字段必须填写符合邮箱格式的数据
email = forms.EmailField()
如何去校验数据
三层校验
类中的字段校验
方法中的校验
钩子函数进行校验
点击python console
# 传入待校验的数据 用自己写的类 传入的字典格式的待校验的数据
form_obj = views.MyRegForm({'username':'jason','password':'12','email':'123456'})
# 判断数据是否符合校验规则
form_obj.is_valid()
False
# 如何获取校验之后通过的数据
form_obj.cleaned_data
结果:
{'username': 'jason'}
# 如何获取校验失败的数据
form_obj.errors
结果:
{
'password': ['Ensure this value has at least 3 characters (it has 2).'],
'email': ['Enter a valid email address.']
}
# forms主键默认的所有的字段都必须传值 传少了一定不行 但是传多了却可以 只校验类里面写的字段 多的自动忽略
form_obj = views.MyRegForm({'username':'jason','password':'123456'})
form_obj.is_vaild()
False
form_obj.errors
结果:
{'email': ['This field is required.']}
form_obj = views.MyRegForm({'username':'jason','password':'123456','email':'123@qq.com','hobby':'adada'})
form_obj.is_vaild()
form_obj.cleaned_data
结果:{'username': 'jason', 'password': '123456', 'email': '123@qq.com'}
form_obj.errors
{}
如何渲染页面
还是需要先写类
class MyRegForm(forms.Form):
# 用户名最少3位最多8位
username = forms.CharField(max_lenth=8, min_length=3, label='用户名', error_messages={
'max_length': '用户名最长8位',
'min_legth': '用户名最短3位',
'required': '用户名不能为空'
},required=False, initial='jason',widget=forms.widgets.TextInput(attrs={'class':'form-control c1 c2'}))
password = forms.CharField(max_length=8, min_length=3, label='密码', widget=forms.widgets.PasswordInput(attrs={'class':'form-control'}))
confirm_password = forms.CharField(max_length=8, min_length=3, label='确认密码', widget=forms.widgets.PasswordInput(attrs={'class':'form-control'}))
# email字段必须填写符合邮箱格式的数据
email = forms.EmailField(label='邮箱', error_messages={
'required': '邮箱必填',
'invalid': '邮箱格式不正确'
})
phone = forms.CharField(
validators=[
RegexValidator(r'^[0-9]+$','请输入数字'),
RegexValidator(r'^159[0-9]+$','数字必须以159开头')
])
了解其他字段渲染
gender = forms.ChoiceField(
choices=((1, "男"), (2, "女"), (3, "保密")),
label="性别",
initial=3,
widget=forms.widgets.RadioSelect()
)
hobby = forms.ChoiceField(
choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
label="爱好",
initial=3,
widget=forms.widgets.Select()
)
hobby1 = forms.MultipleChoiceField(
choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
label="爱好",
initial=[1, 3],
widget=forms.widgets.SelectMultiple()
)
keep = forms.ChoiceField(
label="是否记住密码",
initial="checked",
widget=forms.widgets.CheckboxInput()
)
hobby2 = forms.MultipleChoiceField(
choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
label="爱好",
initial=[1, 3],
widget=forms.widgets.CheckboxSelectMultiple()
)
forms组件只帮你渲染获取用户输入(输入 选择 下拉 文件)的标签 不渲染按钮和form表单标签 渲染出来的每一个input提示信息都是类中字段首字母大写
<p>第一种渲染方式:多个p标签 本地测试方便 但是封装程度太高 不便于扩展</p>
三种方式:
{{ form_obj.as_p }}
{{ form_obj.as_ul }}
{{form_obj.as_table }}
<p>第二种渲染方式: 扩展性较高 书写比较繁琐</p>
<label for='{{ form_obj.username.id_for_label }}'>
{{ form_obj.username.label }}</label>
{{ form_obj.username }}
{{ form_obj.password.label }}{{ form_obj.password }}
{{ form_obj.email.label }}{{ form_obj.email }}
<p>第三种渲染方式 推荐使用</p>
{% for form in form_obj %}
<p>
{{ form.label }}{{ form }}
</p>
{% endfor %}
如何渲染错误信息
前端
<form action='' method='post' novalidate>
{% for form in form_obj %}
<p>
{{ form.label }}{{ form }}
<span>{{ form.errors.0 }}</span> # 这个是模板语法 索引不会溢出报错
</p>
{% endfor %}
<input type='submit'>
</form>
后端
def reg(request):
# 首先生成一个空的对象
form_obj = MyReForm()
if request.method == 'POST':
# 获取用户数据并交给forms组件校验 request.POST
form_obj = MyRegForm(request.POST)
# 获取校验结果
if form_obj.is_valid():
return HttpRespnse('数据没有问题')
else:
# 获取校验失败的字段和提示信息
print(form_obj.errors)
# 直接将该对象传给前端页面
return render(request, 'reg.html', locals())
数据校验前后端都要有,但是前端的校验弱不禁风,可有可无,而后端的校验则一定要非常全面
如何取消浏览器自动帮我们校验的功能
form表单取消前端浏览器自动校验功能
<form action='' method='post' novalidate>
常用的参数
label input提示的信息
error_messages 自定义报错的提示信息
required 设置字段是否允许为空
initial 设置默认值
widget 控制type类型及属性 多个类型用空格隔开即可
widget = forms.widgets.TextIput(attrs={ 'class': 'form-control c1 c2' })
widget = forms.widgets.PasswordInput(attrs={'class':'form-control})
钩子函数 (类中的方法)
全局钩子(针对多个字段)
校验密码与确认密码是否一致
局部钩子 (针对单个字段)
校验用户名中不能包含666
全局钩子:实现校验密码与确认密码是否一致
def clean(self):
# 校验密码与确认密码是否一致
password = self.cleaned_data.get('password')
confirm_password = self.cleaned_data.get('confirm_password')
if not password == confirm_password:
# 展示信息
self.add_error('confirm_password','两次密码不一致')
return self.cleaned_data
局部钩子:用户名中不能包含666
def cleaned_username(self):
username = self.cleaned_data.get('username')
if '666' in username:
self.add_error('username','不可含有666')
return username
如果想要同时操作多个字段的数据就去使用全局钩子
如果先要操作单个字段的数据 就去使用局部钩子
Django操作cookie与session
cookie与session的作用
保存信息
当你第一次登录成功后,服务端会给你返回一个随机字符串,保存客户端浏览器上,之后再次朝服务端发请求,只需要携带该随机字符串,服务端就能识别用户当前的身份
cookie虽然是保存在客户端的浏览器上的,但是是服务器设置的浏览器也是可以拒绝服务器的要求,不保存cookie
cookie
保存在客户端浏览器上的键值对
return HttpResponse(), render(), redirect()
变形
obj = HttpResponse(), render(), redirect()
return obj
设置cookie
obj.set_cookie()
获取cookie
request.COOKIES.get()
删除cookie
obj.delete_cookie()
request.path_info 只拿路径部分 不拿参数
request.path_info: /home/
request.get_full_path 拿路径加参数
request.get_full_path(): /home/?username=jason&password=123
# 装饰器
from functools import wraps
def login_auth(func):
@wraps(func)
def inner(request,*args,**kwargs):
# print('request.path_info:',request.path_info)
# print('request.get_full_path():',request.get_full_path())
# 执行被装饰函数之前你可以做的事情
target_url = request.path_info
if request.COOKIES.get('username'):
res = func(request,*args,**kwargs)
return res
else:
return redirect('/login/?next=%s'%target_url)
return inner
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
if username == 'jason' and password == '123':
# target_url = request.GET.get("next",'/home/')
target_url = request.GET.get("next")
# 判断用户登录之前是否有想要访问的url
if target_url:
# 保存用户登录状态
obj = redirect(target_url)
else:
obj = redirect('/home/')
# 设置cookie
obj.set_cookie('username','jason666',max_age=3)
return obj
return render(request,'login.html')
@login_auth
def home(request):
# 校验浏览器是否有对应的cookie
# if request.COOKIES.get('username'):
# print(request.COOKIES)
# return HttpResponse("我是home页面 只有登录的用户才能访问")
# else:
# return redirect('/login/')
return HttpResponse("我是home页面 只有登录的用户才能访问")
@login_auth
def index(request):
return HttpResponse('我是index页面 只有登录之后的用户才能看')
@login_auth
def demo(request):
return HttpResponse('我是demo页面 只有登录之后的用户才能看')
@login_auth
def logout(request):
obj = HttpResponse('注销了')
obj.delete_cookie('username')
return obj
session
保存在服务端上的键值对
设置
request.session['key'] = value
1.django内部会自动生成一个随机字符串
2.去django_session表中存储数据 键就是随机字符串 值是要保存的数据(由中间件来做)
3.将生成好的随机字符串返回给客户端浏览器,浏览器保存键值对
sessionid 随机字符串
获取
request.session.get('key')
1.django会自动去浏览器的cookie查找sessionid键值对,获取随机字符串
2.拿着该随机字符串去django_session表中比对数据
3.如果比对上了 就将随机字符串对应的数据获取出来并封装到
request.session提供用户调用
djang中默认的session超时时间为14天
设置会话session,cookie的超时时间
request.session.set_expiry(value)
如果value是个整数,session会在这些秒以后失效
如果value是个datatime或timedelta,session就会在这个时间后失效
如果value是0,用户关闭浏览器session就后悔失效
如果value是None,session会依赖全局session失效策略
删除当前会话的所有session数据
request.session.delete()
删除当前会话的数据,并删除会话的cookie 推荐使用
request.sesson.flush()
这用于确保前面的会话数据不可以再次被用户的浏览器访问,例如,django.contrib.auth.logout() 函数中就会调用它
django_session表还可以当做一个临时的仓库
原文地址:https://www.cnblogs.com/godlover/p/12193103.html
- [WCF 4.0新特性] 默认绑定和行为配置
- mysql数据库及django用户名启用中文的方法
- 【学习笔记】先行者课程0109-rotate3d_变量、堆、栈
- 通过WCF扩展实现消息压缩
- Linux系统中的信号量机制
- 基于Linux与lpc3250开发板的交叉开发环境搭建
- WCF中关于可靠会话的BUG!!
- [WCF安全系列]谈谈WCF的客户端认证[Windows认证]
- ls命令实现分析
- [WCF安全系列]谈谈WCF的客户端认证[X.509证书认证]
- Openstack Trove概要
- [WCF安全系列]实例演示:TLS/SSL在WCF中的应用[SSL over TCP]
- [WCF安全系列]谈谈WCF的客户端认证[用户名/密码认证]
- [WCF安全系列]绑定、安全模式与客户端凭证类型:BasicHttpBinding
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 文件分割与合并
- 其他流---基本数据处理流
- 其他流---字节数组流与文件流对接
- 其他流---字节流数组
- 字符流出现乱码问题
- 缓冲流---为字节流和字符流复制文件增加缓冲流
- 字符流---输入输出与复制文本文件
- Spring 中的几个 PostProcessor 的区别与联系
- Spring 中基于注解的事务控制及原理分析
- Spring 中根据环境切换配置 @Profile
- Spring 中的属性赋值
- Spring 中控制 Bean 生命周期的几种方式及 BeanPostProcessor 执行原理
- Spring 中的 @Import 注解及向容器中添加 Bean 的几种方式
- Spring 注解开发之 @Conditional
- JDBC 技术应用实践:网上书城后台管理系统