首页 > 技术文章 > Form组件

xzqpy 2019-06-17 20:57 原文

摘要:是否在ORM写完之后,不知道如何统一在前端验证格式?还在为用户乱输入而犯难?不用着急,我们的form组件统统帮您搞定

 

前戏:小细节

1.提交表单 所有的数据会依然存在,但是password例外,可以设置render_value=True

2.as_ul 渲染 字段不写label 默认为字段名首字母大写展示到页面

3.foo.error 拿到的是 li标签  foo.error.0是span标签

4.如果在保存数据库数据的时候,想要modes.user.create(**request.POST) 这么传可以吗
可以,只要保证form组件字段与models字段相同就行

5.钩子函数什么时候执行,全部校验通过,额外进行校验

6.钩子函数一定返回结果
7.注意widgets需要导入 无法使用forms.widgtes

 

 

 

 

 

Form组件的基本定义

它和我们的模型表相似,不过它是为了校验数据格式

from django.forms import  Form
from django import forms
from django.forms import widgets
class  MyForm(Form):
    email=forms.EmailField(max_length=18,min_length=6,label="邮箱",error_messages={
        "min_length":"小弟a ,你不行哦",
        "invalid":"格式问题"})

    password=forms.CharField(max_length=18,min_length=6,label="密码",error_messages={
        "max_length":"哥哥,太长了,我怕疼",
        "min_length":"小弟,你不行哦", 
        "required":"必须来"},widget=widgets.PasswordInput(render_value=True))

    re_password=forms.CharField(max_length=18,min_length=6,label="密码",error_messages={
        "max_length":"哥哥,太长了,我怕疼",
        "min_length":"小弟,你不行哦",
        "required":"必须来"})
定义Form组件

 

如何去渲染我们的组件

把我们的form组件返回前端

def reg(request):
    myForm=MyForm()
    return  render(request,"reg.html",locals())

前端渲染我们的组件

场景一:适合不需要自己扩展额外的场景
注意:不是form表单 
{{ form_obj.as_p }} #由P标签包裹
{{ form_obj.as_ul }}#由li标签包裹

场景二:自己手动写标题和input
<form action="" method="post">
<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>

场景三:直接for循环form组件
<form action="">
{% for foo in form_obj %} #foo相当于 form_obj.name
<p>{{ foo.label }}{{ foo }}</p>
{% endfor %}
</form>

 

 

后端校验格式是否正确

流程:post请求后,判断实例化对象是否通过验证,不通过的话返回原来页面,不过错误的东西会在组件里,返回给前端

def reg(request):
    myForm=MyForm()
    if request.method=="POST":
        myForm = MyForm(request.POST)#把数据实例化 ,校验
        if myForm.is_valid(): #可以判断是否校验成功
            print(myForm.cleaned_data) #通过的都放在这里 ,不通过的字段都在form_obj.error里
            return HttpResponse("校验通过")
        else :
            print(myForm.errors) #可以拿到不通过的字段
    return  render(request,"reg.html",locals())

 

为了防止前端优先校验,我们关闭前端校验:<form action="" method="post" novalidate>

<form action="" method="post" novalidate>
    {% for foo in myForm %}
        <p>{{ foo.label }}{{ foo }}</p>
        <span>{{ foo.errors.0 }}</span>  #先当与组件对象.字段.错误拿到erros_list
    {% endfor %}
    <input type="submit">
</form>

 

想验证成功后,继续做额外校验——钩子函数

什么时候执行?:实例化的时候,当通过所有的校验(全为正确) 就执行钩子函数

局部钩子(判断一个字段错误)

实例化没有错误,会验证这个字段是否还要自定义错误,一般错误的话加入到error里

 

示例:验证这个邮箱 是否被注册

def clean_email(self):
    email=self.cleaned_data.get("email")
     if email=="492557688@qq.com":
            self.add_error("email","不好意思,这个是小强专属")
        return  email #一定要加上
全局钩子(判断两个字段错误)

示例:验证两次密码是否一致

def clean(self):
    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

 

每个form字段都是input?

可以在form字段参数widget修改

示例:把密码从text 改为password

password=forms.CharField(max_length=18,
min_length=6,
label="密码",
widget=widgets.PasswordInput(render_value=True)
)

 

为每个form字段input框添加额外的属性?

示例:为密码框添加 class=c1

password=forms.CharField(max_length=18,
                         min_length=6,
                         label="密码",
                         widget=widgets.PasswordInput(attrs={"class":"c1"})
                         )

 

推荐阅读