一、django form 组件
1、注册功能 1.渲染前端标签获取用户输入 >>> 渲染标签 2 .获取用户输入传递到后端校验 >>> 校验数据 3.校验未通过展示错误信息 >>> 展示信息 例子: def register(request): error = {'username': '', 'password': ''} if request.method == 'POST': username = request.POST.get('username') password = request.POST.get('password') if 'sb' in username : error['username'] = '你才是sb' if password == '123': error['password'] = '密码太简单' return render(request, 'register.html', locals()) html页面: <form action="" method="post" > <p >username: <input type="text" name="username"><span>{{ error.username }}</span></p> <p >password: <input type="password" name="password"><span>{{ error.password }}</span></p> <input type="submit"class="btn btn-success"> </form> 校验数据,校验前端后端都可以做,但是前端可以不做,后端必须得做!!!
2、django form 组件 应该做到的三个功能
渲染标签
校验数据
展示信息
前提:先定义一个对象,实例化的时候不用传参 from django import forms class MyForm(forms.Form): name = forms.CharField(max_length=6,label='用户名') password = forms.CharField(max_length=8,min_length=3,label='密码') email = forms.EmailField(label='邮箱') def register(request): #生成一个空函数 form_obj = MyForm() return render(request,'register.html',locals()) form组件只帮你渲染获取用户输入的标签,不会帮你渲染提交按钮,需要手动添加 <h1>第一种渲染方式(可扩展性较差)</h1> {{ form_obj.as_p }} {{ form_obj.as_ul }} 封装程度太高 <h1>第二种渲染方式</h1> <form action=""> <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> <h1>第三种渲染标签的方式</h1> <form action=""> {% for foo in form_obj %} <p>{{ foo.label }}{{ foo }}</p> {% endfor %} </form> 前端取消校验 添加 novalidate 字段即可 <form action="" method="post" novalidate></form>
第一步需要一个form类 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对象 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校验规则)
form组件提交数据如果数据不合法,页面上会保留之前用户输入的信息 def register(request): #生成一个空函数 form_obj = MyForm() if request.method == 'POST': print(request.POST) #<QueryDict: {'name': ['老李'], 'password': ['123'], 'email': ['119@qq.com']}> form_obj = MyForm(request.POST) #前端将数据传给后端,后端拿到数据,重新生成一个实例化的同名对象 if form_obj.is_valid(): return HttpResponse('ok') return render(request,'register.html',locals()) #此时如果数据格式不正确,html页面会走上两次,就会产生提交数据后,原始的数据继续保留的情况 在前端页面,后端校验,即通过form_obj对象里含有errors属性,在前端取值,注意errors是一个列表形式的,需要索引取值 <form action="" novalidate method="post"> {% for foo in form_obj %} <p>{{ foo.label }} {{ foo }}<span>{{ foo.errors.0}}</span></p> {% endfor %} <input type="submit"> </form> 设置前端报错信息的样式: from django import forms class MyForm(forms.Form): username = forms.CharField(max_length=6,label='用户名',error_messages={ 'max_length':'用户名最长6位', 'required':'用户名不能为空', }) password = forms.CharField(max_length=8,min_length=3,label='密码',error_messages={ 'max_length':'最长为8位', 'min_length':'最短为3位', 'required':'密码不能为空' }) email = forms.EmailField(label='邮箱',error_messages={ 'invalid':'邮箱格式不正确', 'required':'邮箱不能为空'}) 补充:可以设定输入值为空 required=True <form action="" method="post" novalidate> 前端中取消校验 novalidate 保存数据 创建的对象时拿到的正确数据,可以直接**form_obj.cleaned_data传入类中 from app1 import models def register(request): form_obj = MyForm() if request.method == 'POST': print(request.POST) form_obj = MyForm(request.POST) if form_obj.is_valid(): #将返回的信息保存 # print(form_obj.cleaned_data) 是满足校验的字典类型的数据 models.User.objects.create(**form_obj.cleaned_data) return render(request,'register.html',locals()) 补充:需要保证字段名的一致,即models里的字段,与继承forms.Form 类下的字段要保证一致 前端取消校验,并显示错误提示 <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
3、钩子函数 用来对字段进行校验
# 局部钩子函数 (单个字段的校验利用局部钩子函数) def clean_name(self): username = self.cleaned_data.get('username') if '666' in username: self.add_error('username','光喊666是不行的,要有真实力!') return username # 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
4、常用字段及插件
创建Form类时,主要涉及到 【字段】 和 【插件】,字段用于对用户请求数据的验证,插件用于自动生成HTML;
initial
初始值,input框里面的初始值。
class LoginForm(forms.Form): username = forms.CharField( min_length=8, label="用户名", initial="张三" # 设置默认值 ) pwd = forms.CharField(min_length=6, label="密码")
error_messages
重写错误信息。
class LoginForm(forms.Form): username = forms.CharField( min_length=8, label="用户名", initial="张三", error_messages={ "required": "不能为空", "invalid": "格式错误", "min_length": "用户名最短8位" } ) pwd = forms.CharField(min_length=6, label="密码")
password
加密,也可以添加css样式
class LoginForm(forms.Form): ... pwd = forms.CharField( min_length=6, label="密码", widget=forms.widgets.PasswordInput(attrs={'class': 'c1'}, render_value=True) )
radioSelect
单radio值为字符串
class LoginForm(forms.Form): username = forms.CharField( min_length=8, label="用户名", initial="张三", error_messages={ "required": "不能为空", "invalid": "格式错误", "min_length": "用户名最短8位" } ) pwd = forms.CharField(min_length=6, label="密码") gender = forms.fields.ChoiceField( choices=((1, "男"), (2, "女"), (3, "保密")), label="性别", initial=3, widget=forms.widgets.RadioSelect() )
单选Select
class LoginForm(forms.Form): ... hobby = forms.ChoiceField( choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ), label="爱好", initial=3, widget=forms.widgets.Select() )
多选Select
class LoginForm(forms.Form): ... hobby = forms.MultipleChoiceField( choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ), label="爱好", initial=[1, 3], widget=forms.widgets.SelectMultiple() )
单选checkbox
class LoginForm(forms.Form): ... keep = forms.ChoiceField( label="是否记住密码", initial="checked", widget=forms.widgets.CheckboxInput() )
多选checkbox
class LoginForm(forms.Form): ... hobby = forms.MultipleChoiceField( choices=((1, "篮球"), (2, "足球"), (3, "双色球"),), label="爱好", initial=[1, 3], widget=forms.widgets.CheckboxSelectMultiple() )