1.渲染前端标签获取用户输入 >>> 渲染标签 2.获取用户输入传递到后端校验 >>> 校验数据 3.校验未通过展示错误信息 >>> 展示信息
1.渲染标签
2.校验数据
3.展示信息
校验前端后端都可以做,但是前端可以不做,后端必须得做!!!
from django import forms class MyForm(forms.Form): name = forms.CharField(max_length=6) password = forms.CharField(max_length=8,min_length=3) email = forms.EmailField(required=True)
form_obj = MyForm({‘name‘:‘jason‘})
form_obj.is_valid() # 只有当所有的字段都校验通过才会返回True
form_obj.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.‘] }
form_obj.cleaned_data # 符合校验规则数据都会被放到该对象中 ps:form组件校验数据的规则从上往下依次取值校验 校验通过的放到cleaned_data 校验失败的放到errors 注意: form中所有的字段默认都是必须传值的(required=True) 校验数据的时候可以都传(多传的数据不会做任何的校验>>>不会影响form校验规则)
class MyForm(forms.Form): name = forms.CharField(label=‘用户名‘,max_length=8,error_messages={ ‘max_length‘:‘用户名最长8位‘, ‘required‘:‘用户名不能为空‘ },widget=forms.TextInput(attrs={‘class‘:‘form-control‘})) password = forms.CharField(label=‘密码‘,min_length=3,max_length=8,error_messages={ ‘max_length‘:‘密码最长8位‘, ‘min_length‘:‘密码最短3位‘, ‘required‘:‘密码不能为空‘, },widget=forms.PasswordInput(attrs={‘class‘:‘form-control c1‘})) password1 = forms.CharField(label=‘密码‘,min_length=3,max_length=8,error_messages={ ‘max_length‘:‘密码最长8位‘, ‘min_length‘:‘密码最短3位‘, ‘required‘:‘密码不能为空‘, },widget=forms.PasswordInput(attrs={‘class‘:‘form-control‘})) email = forms.EmailField(error_messages={ ‘invalid‘:‘邮箱格式不正确‘, ‘required‘:‘邮箱不能为空‘ },widget=forms.EmailInput(attrs={‘class‘:‘form-control‘})) def reg(request): form_obj = MyForm() #一定要实例化 if request.method == ‘POST‘: form_obj =MyForm(request.POST) if form_obj.is_valid(): models.User.objects.create(**form_obj.cleaned_data) return render(request,‘reg.html‘,locals())
form组件提交数据如果数据不合法,页面上会保留之前用户输入的信息
在使用form组件对模型表进行数据校验的时候,只需要保证字段一致
那么在创建的对象的时候你就直接**form_obj.cleaned_data
<p>{{ form_obj.name.label_tag }}{{ form_obj.name }}</p> <p>{{ form_obj.password.label_tag }}{{ form_obj.password }}</p> <p>{{ form_obj.password1.label_tag }}{{ form_obj.password1 }}</p> <p>{{ form_obj.email.label_tag }}{{ form_obj.email }}</p> <input type="submit">
前端取消校验加上novalidate
<form action="" method="post" novalidate> {% for foo in form_obj %} <p>{{ foo.label_tag }}{{ foo }} <span>{{ foo.errors.0 }}</span> </p> {% endfor %} <input type="submit"> </form>
创建Form类时,主要涉及到 【字段】 和 【插件】,字段用于对用户请求数据的验证,插件用于自动生成HTML;
gender = forms.ChoiceField(
choices=((1,‘男‘),(2,‘女‘),(3,‘保密‘)),
label=‘性别 ChoiceField单选圆点框‘,
initial=3,
widget=forms.RadioSelect()
)
hobby = forms.ChoiceField(
choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
label="爱好 Select单选下拉框",
initial=3,
widget=forms.Select()
)
hobby1 = forms.MultipleChoiceField(
choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
label="爱好 MultipleChoiceField多选选择框",
initial=[1, 3],
widget=forms.widgets.SelectMultiple()
)
keep = forms.ChoiceField(
label="是否记住密码 ChoiceField单选框",
initial="checked",
widget=forms.widgets.CheckboxInput()
)
hobby2 = forms.MultipleChoiceField(
choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
label="爱好 MultipleChoiceField多选框",
initial=[1, 3],
widget=forms.widgets.CheckboxSelectMultiple()
)
初始值,input框里面的初始值。
重写错误信息
获取密码密文样式
# 函数名称必须以 claen_字段名 的格式 def clean_name(self): # 目的:如果用户名已经注册,则报异常 val = self.cleaned_data.get(‘name‘) ret = UserInfo.objects.filter(name=val) if not ret: return val else: raise ValidationError(‘用户名已经被注册‘) def clean_tel(self): # 目的:校验手机号码长度为11 val = self.cleaned_data.get(‘tel‘) if len(val) == 11: return val else: raise ValidationError("手机号码格式错误")
def clean_name(self): name = self.cleaned_data.get(‘name‘) if ‘666‘ in name: self.add_error(‘name‘,‘喊你妹666啊‘) return name
在写注册用户的时候,有输入密码,确认密码,可以进行布局钩子处理,处理完毕是不是在进行判断,判断其是否相等,相等的话就存到数据库中,不相等就抛出异常。
全局钩子主要应用场景就是每次校验多个字段,而局部钩子每次取的是单个字段,单个变量。
def clean(self): password = self.cleaned_data.get(‘password‘) password1 = self.cleaned_data.get(‘password‘) if not password == password1: self.add_error(‘password1‘,‘两次密码不一致‘) return self.cleaned_data
1、基础TCP/IP作用于应用层的协议
2、基于请求响应
3、无状态
4、无连接
保存在客户端/浏览器上的键值对
保存在服务端的键值对
服务端产生的字符串返回给客户端,服务端负责找个地方存储用户的会话信息{‘随机字符串‘:’敏感信息’},session依赖于cookie
cookie是通过在客户端记录信息确定用户身份,Session是通过在服务端记录信息确定用户身份。
服务器会生成两个相同cookie字符串,一份本地保存,一份发送给浏览器,等下次浏览器发送请求时,会将信息和cookie字符串一同发给服务端本地保存的cookie字符串做校验比对,如果相同就表示登录成功,服务端保存用户登录成功的状态,Django的session保存在数据库就是一个大字典,key就是cookie字符串,value仍然是一个字典,字典的key和value存放了用户的相关信息,方便存取session里的信息
obj.set_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‘) user =models.User.objects.filter(name=username,password=password).first() if user: old_path = request.GET.get(‘next‘) if old_path: obj = redirect(old_path) else: obj =redirect(‘/home/‘) obj.set_cookie(‘name‘,‘zyl‘,max_age=5) return obj return render(request,‘login.html‘)
登录前:
登录后
没加装饰器之前在login中登录之后再打开home,xxx页面会显示未登录,加上装饰器做登录判断
from functools import wraps def login_auth(func): @wraps(func) def inner(request,*args,**kwargs): old_path = request.get_full_path() if request.COOKIES.get(‘name‘): return func(request,*args,**kwargs) return redirect(‘/login/?next=%s‘%old_path) return inner
def delete_cookie(request): rep = redirect("/login/") rep.delete_cookie("name") # 删除用户浏览器上之前设置的name rcookie值 return rep
def set_session(request): request.session[‘name‘]=‘zyl‘ request.session[‘name1‘]=‘jason‘ request.session[‘name2‘]=‘tank‘ return HttpResponse(‘ok‘)
# 1.先生成一个随机的字符串
# 2.在django session表中存储该随机字符串与数据的记录
# 3.将随机的字符串发送给客户端浏览器
浏览器会设置一个键为sessionid来存放session值
def get_session(request): print(request.session.get(‘name‘)) print(request.session.get(‘name1‘)) print(request.session.get(‘name2‘)) return HttpResponse(‘获取session‘) 1.django自动获取浏览器随机字符串取django session表里面比对 2.如果比对成功 会将当前随机字符串对应的数据赋值给request.session 3.通过request.session操作该数据(数据不存在也不会影响我们的业务逻辑)
def delete_session(request): request.session.delete() return HttpResponse(‘删除数据库中的session‘)
def flush_session(request): request.session.flush() return HttpResponse(‘删除表和浏览器的session‘)
原文:https://www.cnblogs.com/zhengyuli/p/11042775.html