django为我们提供了forms组件,可以让我们非常方便的渲染前端页面、接收及验证前端发送到后端的数据。、
forms组件不会将用户的输入清空
1.forms组件基本使用
后端代码
views.py
---------------------------------------
from django import forms
class MyRegForm(forms.Form):
username = forms.CharField(max_length=8, min_length=3)
password = forms.CharField(max_length=8, min_length=3)
email = forms.EmailField()
def register(request):
# 生成一个自定义的form组件对象
form_obj = MyRegForm()
if request.method == 'GET':
return render(request, 'register.html', locals())
form_obj = MyRegForm(request.POST)
return render(request, 'register.html', locals())
前端代码
<form action="" method="post" novalidate>
{% for input_obj in form_obj %}
<p>
<label for="{{ input_obj.id_for_label }}">
{{ input_obj.label }}
</label>
{{ input_obj }}
<span>{{ input_obj.errors.0 }}</span>
</p>
{% endfor %}
<input type="submit" value="提交">
</form>
后端常用方法
# form_obj本质上是根据我们定义的类封装了html代码,根据django的模版语法再渲染到html文件中
# form_obj常用方法
# 1.初始化form组件对象
form_obj = MyRegForm(request.POST)
# 2.检验form中的数据是否全部合法(可多不可少)
form_obj.is_valid()
# 3. 返回验证通过的数据。
form_obj.cleaned_data
# 4.如何获取校验失败及失败的原因
form_obj.errors
{
'password': ['Ensure this value has at least 3 characters (it has 2).'],
'email': ['Enter a valid email address.']
}
前端渲染
<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循环
要注意的是forms组件在前端自带校验功能,但前端源码容易被修改,必须在后端进行校验后再对数据进行操作。
前端校验只可作为用户提示。
<form action="" method="post" novalidate> # 取消前端校验
2.常用参数
label # 每个input的标签内容,默认为字段名首字母大写
error_messages # 自定义报错的提示信息
username = forms.CharField(max_length=8, min_length=3,
error_messages={
'max_length': '最大长度为8',
'min_length': '最小长度为3',
'required':'不能为空', # 为空时的提示信息
})
required # 默认为True表示必填
widget # 控制type的类型及属性
password = forms.CharField(max_length=8,min_length=3,
widget=forms.widgets.PasswordInput(attrs={'class':'form-control c1 c2'})
)
3.钩子函数
django中勾子函数分为全局钩子和局部钩子。全局勾子函数一般用于字段与字段之间的关系处理,如注册时两次密码确认。局部勾子一般用于某个字段的检验,如检查用户名是否有非法字符。
def clean(self):
# print('全局钩子....')
# username = self.cleaned_data.get('username')
# print(username,'全局钩子','username')
# password = self.cleaned_data.get('password')
# print(password, '全局钩子', 'password')
password = self.cleaned_data.get('password')
re_password = self.cleaned_data.get('re_password')
if password != re_password:
self.add_error('re_password','两次密码不一致')
return self.cleaned_data # 注意return
def clean_username(self):
print('局部钩子...')
username = self.cleaned_data.get('username')
if '666' in username:
self.add_error('username','用户名不能包含666')
return username # 如果不return,clean_data中username就为空
钩子函数的命名非常形象,钩子就像是针对钩取对象中的某个字段进行处理,然后将改字段返回,勾过来记得放回去。
钩子函数的几个注意点:
- 勾出来的数据一定要返回
- 局部钩子函数只有在这个局部的字段通过基本的校验才会被执行(如用户名如果不满足3-8位的要求,就不会去执行clean_username)
- 全局钩子则无论如何都会执行
4.正则校验
from django.core.validators import RegexValidator
phone = forms.CharField(
validators=[
RegexValidator(r'^[0-9]+$', '请输入数字'),
RegexValidator(r'^159[0-9]+$', '数字必须以159开头')
]
)
# 其余字段做了解
5.django中的cookie和session
cookie是一种技术,大多情况下用来验证用户是否登录,在用户登录成功后返回给用户的一段随机字符串。当用户接下来访问其他页面时,可通过cookie来识别用户的身份
session是存储在服务端的key,value的一组对应关系。一个cookie对应一个value值,这个值通常是经过序列化后加密的。
cookie
# 设置cookie的方法
obj = HttpResponse('....')
obj = render('....')
obj = redirect('....')
obj.set_cookie('k1','v1')
# 删除cookie
obj.delete_cookie('k1')
# 获取cookie
request.COOKIES.get('k1')
'''
cookie中可以存放用户的一些信息
例如登录前访问的url,在登录后实现自动跳转
'''
session
# 设置session
request.session['name'] = 'egon'
request.session['password'] = '123'
'''
1.django内部会自动生成一个随机字符串
2.去django_session表中存储数据,键时随机产生的字符串,值实际上是一个序列化后的字典经过加密产生的字符串
3.将生成好的key返回给客户端浏览器存储在COOKIE 键名为sessionId中。
'''
# 获取session
request.session.get('name')
'''
1.django会自动去浏览器的cookie中查找sessionId的键的值
2.将该值去数据库django_session的表中比对
3.如果比对上了,就将对应的value值解密反序列化后封装到request.session中
'''
# 删除session
# 删除当前会话的所有Session数据
request.session.delete()
# 删除当前的会话数据并删除会话的Cookie。 推荐使用
request.session.flush()
'''
这用于确保前面的会话数据不可以再次被用户的浏览器访问
例如,django.contrib.auth.logout() 函数中就会调用它。
'''
# 设置会话Session和Cookie的超时时间
'''
request.session.set_expiry(value)
* 如果value是个整数,session会在些秒数后失效。
* 如果value是个datatime或timedelta,session就会在这个时间后失效。
* 如果value是0,用户关闭浏览器session就会失效。
* 如果value是None,session会依赖全局session失效策略。
'''
6.其余不常用字段
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()
)