Django form组件

form组件

1.校验数据

第一步:需要一个form类
	from django import forms
    class MyForm(forms.Form):   
        name=forms.CharField(max_length=6)   #label属性决定后面渲染的时候生成的label文本,没有默认则名称为首字母大写的字段名,如Name
        password=forms.CharField(max_lenth=8,min_length=3)
        email=forms.EmailField(required=True)   #默认是require=True,不能为空
        
第二步:实例化form对象
	form_obj = MyForm({'name':'jason'})
    
第三步:查看数据是否合法
	form_obj.is_valid()  #只有当所有的字段都校验通过才会返回True
    
第四步:查看校验错误的信息
	form_obj.errors  #这里面放的是所有校验未通过的字段和错误提示
    
第五步:查看校验通过的数据
	form_obj.cleaned_data  #符合校验规则数据都会放到该对象的cleaned_data属性中
    
ps:form组件校验数据的规则从上往下依次取值校验
	校验通过的放在cleaned_data
	校验失败的放到errors
    
注意:
	1.form中所有的字段默认都是必须传值的(required=True)
	2.校验的数据可以多传,多传的数据不会进行任何校验,不会影响form校验规则
	3.如果form_obj=MyForm(),不传参数,虽然不合法但是errors中没有错误的字段及错误提示,如果想上面所述的传参,errors中就会有以下数据
    """
	{
		'name': ['Ensure this value has at most 6 characters (it has 7).'], 
		'password': ['Ensure this value has at least 3 characters (it has 2).'], 
		'email': ['Enter a valid email address.']
	}

	"""

2.渲染标签

form组件只帮你渲染获取用户输入的标签,不会帮你渲染提交按钮,需要手动添加

1.第一种渲染方式(可拓展性较差)
	{{form_obj.as_p}}   <!--每条数据都是<P>标签中包括了<label>和<input>-->
    {{form_obj.as_ul}}  <!--#每条数据都是<li>标签中包括了<label>和<input>,没有<ul>标签-->
    
2.第二种渲染方式
	{form action=""}   <!--下面其实和上方as_p的展现有所不同,没有了label但是有文本,同时没有封装说明了可拓展性强,比如可以添加自定义的标签或文本-->
		<p>{{form_obj.name.label}}{{form_obj.name}}</p>
		<p>{{ form_obj.password.label }}{{ form_obj.password }}</p>
		<p>{{ form_obj.email.label }}{{ form_obj.email }}</p>
		<input type="submit">
    {/form}
    
3.第三种渲染方式
	<form action="">   
		{% for foo in form_obj %}  <!--foo等同于上面的字段对象,可是说是第二种的简化版-->
			<p>{{ foo.label }}{{ foo }}</p>
		{% endfor %}
	</form>

前端取消校验
	<form action='' method='post' novalidate>  <!--添加novalidate-->
</form>

3.展示数据

<form action="" method="post" novalidate>
    {% for foo in form_obj %}
    <p>
        {{ foo.label }}{{ foo }}
        <span>{{ foo.errors.0 }}</span>  <!--得到错误信息文本-->
    </p>
    {% endfor %}
    <input type="submit">
</form>

form组件提价数据如果数据不合法,页面上会保留用户输入的信息在使用form组件对模型表进行数据校验的时候,只需要保证字段一致name在创建对象的时候就可以直接**form_obj.cleaned_data,直接打散成关键字实参进行初始化

<!--如果数据合法其实页面上也仍然用户输入的消息(密码是密文的话不会保留),但是通常登录成功后并不会返回登录界面-->

Hook方法(钩子函数)

定义一个Form对象(顺便补充一些知识点)
class LoginForm(forms.Form):
    username = forms.CharField(
        min_length=8,      
        label="用户名",
        initial="张三",     #设置默认值
        error_messages={         #重写错误信息
            "required": "不能为空",    
            "invalid": "格式错误",
            "min_length": "用户名最短8位"   
        },
        widget=forms.widgets.TextInput(attrs={"class": "form-control"})
    )

局部钩子函数

局部钩子函数(单个字段的校验利用局部钩子函数)
def clean_name(self):
	name = self.cleaned_data.get('name')
	if '666' in name:
		self.add_error('name','光喊666是不行的,要有真实力!')
	return name  # return还是要加上的,兼容性考虑

全局钩子

全局钩子(多个字段的校验利用全局钩子函数)
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',"两次密码不一致,你这个dsb!")
		return self.cleaned_data

设置标签样样式

# 设置标签样式
from django import forms
from django.forms import widgets
class MyForm(forms.From)
    	#password
		password =forms.CharField(max_length=8,min_length=3,error_messages={
            'max_length': '密码最长8位',
            'required': '密码不能为空',
            'min_length':'密码最少3位'
		},widget=widgets.PasswordInput(attrs={'class':'c1 form-control'})) #class对应的value保存形式与前端的保存形式一样,只要空格间隔
		
        #单选select
        hobby = forms.ChoiceField(
        	choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
        	label="爱好",
       		initial=3,
        	widget=forms.widgets.Select()
		)
		
        #多选select
      	hobby1 = forms.MultipleChoiceField(
            choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
            label="爱好",
            initial=[1, 3],
            widget=forms.widgets.SelectMultiple()
		)
		
        #单选checkbox
        keep = forms.ChoiceField(
        	label="是否记住密码",
        	initial="checked",
        	widget=forms.widgets.CheckboxInput()
        )
        
        #多选checkbox
        hobby = forms.MultipleChoiceField(
            choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
            label="爱好",
            initial=[1, 3],
            widget=forms.widgets.CheckboxSelectMultiple()
        )
保存在客户端上的键值对(信息)

在返回的时候先获取返回类的对象(HttpResponse,render,redirect),并对对象进行添加属性,最后再返回
obj=HttpResponse(or render or redirect)

设置cookie
	obj.set_cookie() #给浏览器设置cookie
获取cookie
	request.COOKIE.get('name')   #方式一
	request.COOKIE['name']   #方式二
    
用途之一:用户的登录验证(简化版)
def login(request):
	if request.method == 'POST':
		username = request.POST.get('username')
		password = request.POST.get('password')
	if username == 'jason' and password == '123':
		obj = redirect('/home/')
	# 用户登录成功 朝浏览器设置一个cookie
		obj.set_cookie('name','jason',expires=7*24*3600)
		return obj
	return render(request,'login.html')
cookie配合装饰器实现登录验证
def login(request):
	if request.method == 'POST':
		username = request.POST.get('username')
		password = request.POST.get('password')
	if username == 'jason' and password == '123':
		old_path = request.GET.get('next')
		if old_path:
			obj = redirect(old_path)
		else:
			obj = redirect('/home/')
			# 用户登录成功 朝浏览器设置一个cookie
		obj.set_cookie('name','jason',expires=7*24*3600)
		return obj
	return render(request,'login.html')
		
from functools import wraps  #登录验证装饰器
	def login_auth(func):
		@wraps(func)
		def inner(request,*args,**kwargs):
			# 校验cookie
			old_path = request.get_full_path()  #获取跳转前的完整路径
			if request.COOKIES.get('name'):
				return func(request,*args,**kwargs)  #如果已经登录直接进入页面 
			return redirect('/login/?next=%s'%old_path)#如果没有登录,在GET添加原先路径,便于登录后,访问原路径
	return inner

删除cookie信息
obj.delete_cookie('user')  #删除用户浏览器之前设置的usercoookie值

session

设置session
	request.session['name'] = 'jason'
		#1.先生成了一个随机的字符串
		#2.在django session表中存储该随机字符串与数据的记录(其实,这条指令,只是发出了一个信号,生成了临时的缓存,后续还是通过中间键session来进行的)
        #3将随机的字符串发送给客户端浏览器

获取session
	request.session.get('name')#注意此处没大写
    	#1.django自动获取浏览器随机字符串与django session的信息对比
        #2.如果对比成功,会将当前随机字符串对应的数据赋值给request.session
        #3.通过request.session操作改数据(数据不存在也不会影响我们的业务)
        #也就是说get是最后才执行的,会先去对比
        
浏览器会生成一个sessionid的键来存放session的值        

删除当前会话的所有session数据
request.session.delete()   #也就是说,在路浏览器的Cookie数据仍然存在,但是浏览器会把无效的Cookie数据进行删除

#删除当前会话数据并删除会话的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失效策略
#django默认的session存活时间是328小时,2周缺8小时

posted @ 2019-06-17 20:28  Mr-Bear  阅读(104)  评论(0)    收藏  举报