17 forms组件

添加新博客 编辑本博客

yuan先生博客

一、校验字段功能

forms.CharField

forms.EmailField

class UserForm(forms.Form):
    name=forms.CharField(min_length=1,max_length=8)
    email=forms.EmailField()
View Code

form对象方法

  • is_valid()  校验数据,字段键必须和form字段一样,传入的数据能多,单不能少,校验成功返回True,校验错误返回False
  • cleaned_data 存放校验正确的客户端数据
  • errors  校验错误的数据,字典形式。校验字段为键,错误信息为列表类型,可能多个错误信息

校验成功和失败的数据,失败信息打印出来貌似不是字典,实际是字典类型

 获取错误信息通过get方法即可获取,错误信息为列表,可通过[0]方式获取

二、渲染标签

通过Form对象渲染模板中的input标签。避免input标签name属性和Form属性名称不统一,减少模板中代码量

CharField--->text

EmailField--->email

方式一:

view中实例化UserForm

form=UserForm()
return render(request,'reg.html',{"form":form})
View Code

模板中html

<form action="" method="post">
    <p>用户名:{{ form.name }}</p>
    <p>密码:{{ form.pwd }}</p>
    <p>确认密码:{{ form.r_pwd }}</p>
    <p>邮箱:{{ form.email }}</p>
    <p>电话:{{ form.tel }}</p>
</form>
View Code

方式二:

 通过for循环创建标签

给Form类添加label属性,用于label标签显示

class UserForm(forms.Form):
    #默认有个非空规则
    name=forms.CharField(min_length=1,max_length=8,label="用户名")
    pwd=forms.CharField(min_length=6,label="密码")
    r_pwd=forms.CharField(min_length=6,label="确认密码")
    email=forms.EmailField(label="邮箱")
    tel=forms.CharField(label="电话")
View Code

 模板中通过for创建标签

获取选软input标签值也可以用field.auto_id

<form action="" method="post">
    {% csrf_token %}
    {% for field in form %}
        <div><label for="{{ field.id_for_label}}">{{ field.label }}:</label>{{ field }}</div>
    {% endfor %}
    <input type="submit" value="submit">
</form>
View Code

 

方式三:

html中标签被故障,无法自定义排版。可测试用,项目不建议使用。

 

三、显示错误信息以及输入重置功能

主要是模板标签渲染方法

手写input标签,被绑定的数据不会被保留下来,因为压根就没渲染

<form action="" method="POST">
    {% csrf_token %}
    <p>用户名:<input type="text" name="name"><span>{{ form.name.errors.0 }}</span></p>
    <p>密码:<input type="password" name="pwd"><span>{{ form.pwd.errors.0 }}</span></p>
    <p>确认密码:<input type="password" name="r_pwd"><span>{{ form.r_pwd.errors.0 }}</span></p>
    <p>邮箱:<input type="text" name="email"><span>{{ form.email.errors.0 }}</span></p>
    <p>手机:<input type="text" name="tel"><span>{{ form.tel.errors.0 }}</span></p>
    <input type="submit" value="submit">
</form>
View Code

模板渲染input标签,校验成功的数据会保留,但是错误提示信息并非放在自己写的span标签中,可能是其他原因,需查找官方文档

<form action="" method="post">
    {% csrf_token %}
    <p>{{ form.name.label }}:{{ form.name }}<span>{{ form.name.errors.0 }}</span></p>
    <p>{{ form.pwd.label }}:{{ form.pwd }}<span>{{ form.pwd.errors.0 }}</span></p>
    <p>{{ form.r_pwd.label }}:{{ form.r_pwd }}<span>{{ form.r_pwd.errors.0 }}</span></p>
    <p>{{ form.email.label }}:{{ form.email }}<span>{{ form.email.errors.0 }}</span></p>
    <p>{{ form.tel.label }}:{{ form.tel }}<span>{{ form.tel.errors.0 }}</span></p>
    <input type="submit" value="submit">
</form>
View Code

四、自定义Form组件

修改标签类型

默认都是text,可以渲染其他标签,如password,checkbox,select等

from django.forms import widgets

自定义错误信息

required:为空错误

invalid:格式错误

class UserForm(forms.Form):
    #默认有个非空规则
    name=forms.CharField(min_length=1,max_length=8,label="用户名",error_messages={"required":"该字段不能为空"})
    pwd=forms.CharField(min_length=6,label="密码",
                        widget=widgets.PasswordInput)
    r_pwd=forms.CharField(min_length=6,label="确认密码",widget=widgets.PasswordInput())
    email=forms.EmailField(label="邮箱",error_messages={"required":"该字段不能为空",'invalid':'格式错误'})
    tel=forms.CharField(label="电话")
View Code

自定义class格式

 通过widget添加属性

五、组件校验的局部钩子

局部钩子只能获取和校验一个字段

校验数据是否在数据库中已经存在

from django.core.exceptions import ValidationError
from app.models import UserInfo
class UserForm(forms.Form):
    #默认有个非空规则
    name=forms.CharField(min_length=1,max_length=8,label="用户名",error_messages={"required":"该字段不能为空"})
    pwd=forms.CharField(min_length=6,label="密码",
                        widget=widgets.PasswordInput(attrs={"class":"form-control"}))
    r_pwd=forms.CharField(min_length=6,label="确认密码",widget=widgets.PasswordInput())
    email=forms.EmailField(label="邮箱",error_messages={"required":"该字段不能为空",'invalid':'格式错误'})
    tel=forms.CharField(label="电话")

    # 判断数据是否已经在数据库中
    def clean_name(self):
        val=self.cleaned_data.get("name")
        ret=UserInfo.objects.filter(name=val)
        if not ret:
            return val
        else:
            raise ValidationError("该用户已注册")
View Code

钩子源码解析

自定义钩子验证数据

class UserForm(forms.Form):
    #默认有个非空规则
    name=forms.CharField(min_length=1,max_length=8,label="用户名",error_messages={"required":"该字段不能为空"})
    pwd=forms.CharField(min_length=6,label="密码",
                        widget=widgets.PasswordInput(attrs={"class":"form-control"}))
    r_pwd=forms.CharField(min_length=6,label="确认密码",widget=widgets.PasswordInput())
    email=forms.EmailField(label="邮箱",error_messages={"required":"该字段不能为空",'invalid':'格式错误'})
    tel=forms.CharField(label="电话")

    # 通过钩子验证数据,判断数据是否已经在数据库中
    #钩子名称一定是clean_格式
    def clean_name(self):
        val=self.cleaned_data.get("name")
        ret=UserInfo.objects.filter(name=val)
        if not ret:
            return val
        else:
            #数据验证错误一定返回ValidationError
            raise ValidationError("该用户已注册!")
    def clean_tel(self):
        val=self.cleaned_data.get('tel')#取得tel号码
        if len(val)==11:
            return val
        else:
            raise ValidationError('手机号码长度不对!')
View Code

六、全局钩子

如密码与确认密码的对比

父类中的clean方法啥都没做,这里是留给用户的接口。

全局钩子和局部钩子区别:

  • 全局钩子可以获取多个数据
  • 全局钩子校验不正确时,数据任然在cleaned_data中。局部钩子校验失败的则没有在cleaned_data中

 在form类中自定期clean方法

class UserForm(forms.Form):
    #默认有个非空规则
    name=forms.CharField(min_length=1,max_length=8,label="用户名",error_messages={"required":"该字段不能为空"})
    pwd=forms.CharField(min_length=6,label="密码",
                        widget=widgets.PasswordInput(attrs={"class":"form-control"}))
    r_pwd=forms.CharField(min_length=6,label="确认密码",widget=widgets.PasswordInput())
    email=forms.EmailField(label="邮箱",error_messages={"required":"该字段不能为空",'invalid':'格式错误'})
    tel=forms.CharField(label="电话")

    # 通过钩子验证数据,判断数据是否已经在数据库中
    #钩子名称一定是clean_格式
    def clean_name(self):
        val=self.cleaned_data.get("name")
        ret=UserInfo.objects.filter(name=val)
        if not ret:
            return val
        else:
            #数据验证错误一定返回ValidationError
            raise ValidationError("该用户已注册!")
    def clean_tel(self):
        val=self.cleaned_data.get('tel')#取得tel号码
        if len(val)==11:
            return val
        else:
            raise ValidationError('手机号码长度不对!')
    def clean(self):
        pwd=self.cleaned_data.get('pwd')
        r_pwd=self.cleaned_data.get('r_pwd')
        if pwd == r_pwd:
            return self.cleaned_data
        else:
            raise ValidationError("两次密码不一致")
View Code

全局错误在form.errors.get("__all__")中

views中获取

def reg(request):
    if request.method == "POST":
        # userform=UserForm({'name':'ya','email':'123.com','pwd':'123','r_pwd':'123'})
        userform=UserForm(request.POST)#绑定数据的表单
        if userform.is_valid():#校验所有字段
            #如果所有字段校验正确,正确的数据会放在cleaned_data中
            data=userform.cleaned_data
            pass
        else:
            post_data=userform.cleaned_data#校验成功的数据
            err_data=userform.errors#校验错误的数据,字典形式。校验字段为键,错误信息为列表类型,可能多个错误信息
            print(post_data)
            print(err_data)
            print(err_data.get("__all__")[0])
        return render(request, 'reg.html',{"form":userform})
    else:
        form=UserForm()#未绑定数据的表单
        return render(request,'reg.html',{"form":form})
View Code

在views中将全局errors赋值给errors

errors=err_data.get("__all__")
return render(request, 'reg.html',{"form":userform,'errors':errors})
View Code

在模板中通过.0获取即可。这里获取第一个放在模板中获取,避免没有全局错误的时候在views中报错

<form action="" method="post">
    {% csrf_token %}
    <p>{{ form.name.label }}:{{ form.name }}<span>{{ form.name.errors.0 }}</span></p>
    <p>{{ form.pwd.label }}:{{ form.pwd }}<span>{{ form.pwd.errors.0 }}</span></p>
    <p>{{ form.r_pwd.label }}:{{ form.r_pwd }}<span>{{ form.r_pwd.errors.0 }}</span><span>{{ errors.0 }}</span></p>
    <p>{{ form.email.label }}:{{ form.email }}<span>{{ form.email.errors.0 }}</span></p>
    <p>{{ form.tel.label }}:{{ form.tel }}<span>{{ form.tel.errors.0 }}</span></p>
    <input type="submit" value="submit">
</form>
View Code

避免第一步密码不满足长度为4的要求,而提示两次密码不一致的问题,在全局钩子中多加一步验证即可

七、ModelForm需找其他资料学习

 后面的项目实战CRM有使用

posted @ 2018-07-20 08:41  丫丫625202  阅读(128)  评论(0编辑  收藏  举报