一:form组件功能 form 组件: 1.效验 2.页面显示错误信息 3.渲染页面 4.只要错误信息重置
二: form组件的语法:
fm=BookForm({"title":"yuan","price":123,"email":"123"}) fm.is_valid() # 如果效验失败就返回False # 如果效验成功就返回True fm.cleaned_data 返回校成功的数据 {对的数据的键值:对的数据的值} fm.errors 返回效验错误的数据,后面是列表 {‘错的键值‘:[‘错误信息‘,]} 必须先is_valid 才能取出对的和错的数据
注意:
form表单里的所有字段必须给值,如果不给值就会报错,但是如果给的多就不会报错,
clean-data里只有效验成功的字段
三.form 组件应用
实例:注册用户
模型:model.py
class UserInfo(models.Model): user=models.CharField(max_length=32) pwd=models.CharField(max_length=32) email=models.CharField(max_length=32)
form组件: (写在哪个里都可以)
from django.forms import widgets(需要导入)
class UserForm(forms.Form): msg = {"required": ‘该字段不能为空‘, "invalid": "格式错误", "min_length": "长度不可以小于五"} # invalid只适用于邮箱 # error_messages 自定义错误信息,label 自定义lable显示文字 user = forms.CharField(min_length=5, error_messages=msg, label=‘用户名‘, widget=widgets.TextInput(attrs={"class": "form-control"})) pwd = forms.CharField(min_length=5, error_messages=msg, label=‘密码‘, widget=widgets.PasswordInput(attrs={"class": "form-control"})) r_pwd=forms.CharField(error_messages=msg, label=‘确认密码‘, widget=widgets.PasswordInput(attrs={"class": "form-control"})) email = forms.EmailField(error_messages=msg, label=‘邮箱‘, widget=widgets.EmailInput(attrs={"class": "form-control"}))
视图函数:
方式一:
views,py里
def reg(request): if request.method=="GET": return render(request,‘reg.html‘) if request.method=="POST": # 数据校验 # 直接把它放进来做校验就可以request里多一个crsf-token也没事多余一个也不会报错 form=UserFrom(request.POST) if form.is_valid(): print(form.cleaned_data) else: print("来自errorcleaned",form.cleaned_data) print("哈哈",form.errors) # 因为后面是列表所以需要 # print(‘哈哈1‘,form.errors.get(‘user‘)[0]) error=form.errors return render(request,"reg.html",{‘error‘:error})
对应的模板里HTML
# novalidate 让浏览器对你放行不进行拦截 <form action="" method="post" novalidate> {% csrf_token %} <p>用户名<input type="text" name="user"></p><span class="error">{{ error.user.0 }}</span> <p>密码<input type="password" name="‘pwd"></p><span class="error">{{ error.pwd.0 }}</span> <p>邮箱<input type="text" name="email"></p><span class="error">{{ error.email.0 }}</span> <p><input type="submit"></p> </form>
方式二:
views.py
def reg(request): if request.method=="POST": form = UserFrom(request.POST) if form.is_valid(): print(form.cleaned_data) else: error = form.errors return render(request,‘reg.html‘,locals()) form=UserFrom() return render(request, "reg.html", locals())
模板:
# 不能对应加错误 <form action="" method="post"> {% csrf_token %} {{ form.as_p }} <p><input type="submit"></p> </form>
方式三:
模板:
方式三直接传过来,对的不会重置 <form action="" method="post" novalidate> {% csrf_token %} <p>用户名{{ form.user }}</p><span class="error">{{ error.user.0 }}</span> <p>密码{{ form.pwd }}</p><span class="error">{{ error.pwd.0 }}</span> <p>邮箱{{ form.email }}</p><span class="error">{{ error.email.0 }}</span> <p><input type="submit"></p> </form>
方式四:
模板:
{#方式四#} {#用最后这个就行#} <form action="" method="post" novalidate> {% csrf_token %} {% for field in form %} <div> <lable for=‘‘>{{ field.label }}</lable> {{ field }}<span class="error">{{ field.errors.0 }}</span> </div> {% endfor %} <div><input type="submit">提交</div> </form>
field就是:{{form.user}}
form 组件的使用流程:
源码解析is_valid(self)#self是自定义组件对象
self._errors = ErrorDict()
如果不加钩子就结束了,如果加钩子继续:
代码: form=UserForm(request.POST) 类的实例化:实际上是完成一次赋值, self.field={"user":user,‘pwd‘:pwd,"email":email} 后面的值都是类实例化出来的对象,是各自的规则 user=forms.CharField(min_length=5, label="用户名", error_messages=msg, widget=widgets.TextInput(attrs={"class":"form-control"}) ) pwd=forms.CharField(error_messages=msg, label="密码", widget=widgets.PasswordInput(attrs={"class":"form-control"}) ) email=forms.EmailField(error_messages={"invalid":"邮箱格式错误"}, label="邮箱", widget=widgets.EmailInput(attrs={"class":"form-control"}) ) form.is_valid() self._clean_fields() #效验字段 #效验数据 def _clean_fields(self): #field是各自的规则,name是字段字符串 for name, field in self.fields.items(): # value_from_datadict() gets the data from the data dictionaries. # Each widget type knows how to retrieve its own data, because some # widgets split data over several HTML fields. # UserForm({"user":"yuan",‘pwd‘:123,‘email‘:"123"}) if field.disabled: value = self.get_initial_for_field(field, name) else: # value就是 yuan 等 value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name)) try: if isinstance(field, FileField): initial = self.get_initial_for_field(field, name) value = field.clean(value, initial) else: #field是校验规则,value是 yuan 如果校验不成功直接跳到except里 value = field.clean(value) self.cleaned_data[name] = value # 钩子效验,如果自己的校验规则没通过就不会走钩子 if hasattr(self, ‘clean_%s‘ % name): value = getattr(self, ‘clean_%s‘ % name)() # 如果没有直接报错 self.cleaned_data[name] = value #第一个字段通过第一层校验,然后校验钩子 #(钩子是有顺讯的,第一个拿不到第二个值,后面的可以拿到前面的,因为如果干净就有键值 except ValidationError as e: self.add_error(name, e)
# 定义钩子第一层校验如果失败了,局部的钩子就不执行了 def clean_user(self): val = self.cleaned_data.get(‘user‘) print(val) # user_obj = auth.authenticate(username=val) from django.contrib.auth.models import User user_obj=User.objects.filter(username=val).first() print("haha",user_obj) if user_obj: raise ValidationError(‘用户名已存在‘) else: return val def clean_pwd(self): pwd = self.cleaned_data.get(‘pwd‘) if pwd.isdigit(): raise ValidationError(‘密码是纯数字‘) else: return pwd def clean_email(self): import re email = self.cleaned_data.get(‘email‘) if re.search(‘[0-9a-zA-Z][email protected]\.com‘, email): return email else: raise ValidationError(‘请输入格式化为@163.com邮箱‘) # 全局勾的错误的键为"__all___" def clean(self): pwd = self.cleaned_data.get("pwd") r_pwd = self.cleaned_data.get("r_pwd") print(r_pwd) if pwd and r_pwd: if pwd == r_pwd: return self.cleaned_data else: raise ValidationError(‘两次密码不一致!‘) else: return self.cleaned_data
可以给他起个别名,省着显示错误信息得时候还得判断:
def clean(self): password = self.cleaned_data.get(‘password‘) r_pwd= self.cleaned_data.get(‘r_pwd‘) print(password,r_pwd) if password==r_pwd: print(‘haha‘) return self.cleaned_data else: self.add_error(‘r_pwd‘,ValidationError(‘密码不一致‘))
原文地址:https://www.cnblogs.com/2275114213com/p/9942029.html
时间: 2024-10-24 02:57:21