forms组件

校验功能

  • 就是将form表单中的值在post请求发送到服务端时,服务端利用forms组件去检验是否符合规则
  • form表单中的name属性值要和自定义forms组件的字段一致
           <h3>简单form</h3>


            <form action="" method="post" >
                {% csrf_token %}
                <p>用户名<input type="text" name="name"></p>
                <p>密码 <input type="text" name="pwd"></p>
                <p>确认密码 <input type="text" name="r_pwd"></p>
                <p>邮箱  <input type="text" name="email"></p>
                <p>手机号 <input type="text" name="tel"></p>
                <input type="submit">

            </form>
from django.shortcuts import render,HttpResponse

# Create your views here.

"""
1、引入forms组件 
    from django import forms
2、自定义类,继承组件,并指定需要验证的字段和规则,规则默认非空
     class UserForm(forms.Form):
        name=forms.CharField(min_length=4)
        email=forms.EmailField()
3、实例化对象并引用父类方法 is_valid(),验证字段。
    form=UserForm({"name":"yu","email":"123@qq.com"})
    print(form.is_valid()) # 返回布尔值
"""


from django import forms

class UserForm(forms.Form):
    name = forms.CharField(min_length=4)
    email = forms.EmailField()

def reg(request):
    if request.method == "POST":
        print(request.POST)

        # form表单的name属性值应该与forms组件字段名称一致
        form=UserForm({"name":"xiaoming","email":"123@qq.com"})
        print(form.is_valid())  # 返回布尔值

        # 如果定义字段都匹配成功了,其他的不关心,是true
        form=UserForm({"name":"xiaoming","email":"123@qq.com","xxxx":"yyy"})
        print(form.is_valid())  # 返回布尔值

        if form.is_valid():
            print(form.cleaned_data)
            # 验证正常,cleaned_data可以拿到定义字段的字典形式的值{"name":"yuan","email":"123@qq.com"}
            # 没有多存的"xxxx":"yyy"

        else:
            # 有正确的有错误的分别放置:
            form = UserForm({"name": "xi", "email": "123@qq.com", "xxxx": "yyy"})
            print(form.cleaned_data)  # {"email":"123@qq.com"}
            print(form.errors)  # {"name":["对应错误提示信息"]}

            # print(type(form.errors))  # ErrorDict
            # print(form.errors.get("name"))
            # print(type(form.errors.get("name")))    # ErrorList
            # print(form.errors.get("name")[0])  # 拿到错误信息


        # 实际中我们需要验证的是post请求中的数据
        # form表单中name属性和自定义要验证的字段

        form = UserForm(request.POST)


        return HttpResponse('ok')

    return render(request, "reg.html")

标签渲染功能

上述html文件中form表单是自己写的,要保证字段一致。
forms组件还可以自动渲染标签

方式1:

class UserForm(forms.Form):
    name = forms.CharField(min_length=4)
    email = forms.EmailField()
form=UserForm()  # 第一次get请求时生成一个空对象传给html
    return render(request,"reg.html",locals())
             <form action="" method="post">
                {% csrf_token %}
                <p>用户名
                   {{ form.name }}
              </p>
                <p>密码 {{ form.pwd }}</p>
                <input type="submit">
            </form>

方式二:

循环form,起别名

class UserForm(forms.Form):
    name=forms.CharField(min_length=4,label="用户名")
    pwd=forms.CharField(min_length=4,label="密码",)
    r_pwd=forms.CharField(min_length=4,label="确认密码")
    email=forms.EmailField(label="邮箱")
    tel=forms.CharField(label="手机号")
form=UserForm()  # 第一次get请求时生成一个空对象传给html
    return render(request,"reg.html",locals())

             <form action="" method="post">
                {% csrf_token %}
              {{% for field in form %}}

                 <p>
                     <label for="">{{ field.label }}</label>
                     {# 根据字段渲染input标签#}
                     {{ field }}
                 </p>
                <input type="submit">

            </form>

方式三、
在方式二的基础上调用 form.as_p,不建议用,样式没法更改。

            <h3>forms组件渲染方式3</h3>

            <form action="" method="post">
                 {% csrf_token %}

                 {{ form.as_p }}

                 <input type="submit">
            </form>

渲染错误信息

  • 模板里在每个输入行添加span标签,然后利用 form.pwd.errors.0 获取错误信息
  • 校验不全对时重返界面,return render(request, "reg.html", locals())同时保留数据。
def reg(request):
    if request.method == "POST":
        form = UserForm(request.POST)
        if form.is_valid():
            print(form.cleaned_data)  # 所有干净的字段以及对应的值
        else:
            print(form.cleaned_data)  #
            print(form.errors)  # ErrorDict : {"校验错误的字段":["错误信息",]}
            print(form.errors.get("name"))  # ErrorList ["错误信息",]
            return render(request, "reg.html", locals())

    form=UserForm()  # get传给模板,模板自动渲染
    return render(request, "reg.html", locals())
 <form action="" method="post" novalidate>

                {% csrf_token %}
                <p>{{ form.name.label }}
                    {{ form.name }} <span class="pull-right error">{{ form.name.errors.0 }}</span>
                </p>
                <p>{{ form.pwd.label }}
                    {{ form.pwd }} <span class="pull-right error">{{ form.pwd.errors.0 }}</span>
                </p>
                <p>确认密码
                    {{ form.r_pwd }} <span class="pull-right error">{{ form.r_pwd.errors.0 }}</span><span class="pull-right error">{{ errors.0 }}</span>
                </p>
                <p>邮箱 {{ form.email }} <span class="pull-right error">{{ form.email.errors.0 }}</span></p>
                <p>手机号 {{ form.tel }} <span class="pull-right error">{{ form.tel.errors.0 }}</span></p>
                <input type="submit">

            </form>

模板另外一种渲染方式提示错误信息:

<form action="" method="post" novalidate>
    {% csrf_token %}

    {% for field in form %}
        <div>
            <label for="">{{ field.label }}</label>
            {{ field }} <span class="pull-right" style="color: red">{{ field.errors.0 }}</span>
        </div>
    {% endfor %}
    <input type="submit" class="btn btn-default">

</form>

改进参数


"""
widget 定义标签input类型
attrs={"class":"form-control"}定义标签属性,属性名和值
:widget=widgets.PasswordInput(attrs={"class":"form-control"})
自定义错误提示信息:error_messages={"required":"该字段不能为空","invalid":"格式错误"}

"""

class UserForm(forms.Form):
    name=forms.CharField(min_length=4,label="用户名",error_messages={"required":"该字段不能为空"},
                         widget=widgets.TextInput(attrs={"class":"form-control"})
                         )
    pwd=forms.CharField(min_length=4,label="密码",
                        widget=widgets.PasswordInput(attrs={"class":"form-control"})
                        )
    r_pwd=forms.CharField(min_length=4,label="确认密码",error_messages={"required":"该字段不能为空"},widget=widgets.TextInput(attrs={"class":"form-control"}))
    email=forms.EmailField(label="邮箱",error_messages={"required":"该字段不能为空","invalid":"格式错误"},widget=widgets.TextInput(attrs={"class":"form-control"}))
    tel=forms.CharField(label="手机号",widget=widgets.TextInput(attrs={"class":"form-control"}))

局部钩子,再次校验

单独摘出来定义文件,views文件引入

from django import forms

from django.forms import widgets
from app01.models import UserInfo

from django.core.exceptions import NON_FIELD_ERRORS, ValidationError

"""
1、引入错误类型:from django.core.exceptions import NON_FIELD_ERRORS, ValidationError
(源码:如果定义类有此方法,执行方法,如果不通过检测异常类型:ValidationError
                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)
                
2、写'clean_%s'函数,和错误类型ValidationError
3、val=self.cleaned_data.get("tel"),如果通过定义字段的条件,取值
4、定义条件不符合再次报错:raise ValidationError("该用户已注册!")


"""

class UserForm(forms.Form):
    name=forms.CharField(min_length=4,label="用户名",error_messages={"required":"该字段不能为空"},
                         widget=widgets.TextInput(attrs={"class":"form-control"})
                         )
    pwd=forms.CharField(min_length=4,label="密码",
                        widget=widgets.PasswordInput(attrs={"class":"form-control"})
                        )
    r_pwd=forms.CharField(min_length=4,label="确认密码",error_messages={"required":"该字段不能为空"},widget=widgets.TextInput(attrs={"class":"form-control"}))
    email=forms.EmailField(label="邮箱",error_messages={"required":"该字段不能为空","invalid":"格式错误"},widget=widgets.TextInput(attrs={"class":"form-control"}))
    tel=forms.CharField(label="手机号",widget=widgets.TextInput(attrs={"class":"form-control"}))


    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):

        val=self.cleaned_data.get("tel")

        if len(val)==11:

            return val
        else:
            raise  ValidationError("手机号格式错误")
全局:取多个校验字段:
   1、自定义函数def clean(self):覆盖父类方法,返回值和父类一致:self.cleaned_data
   2、 错误信息:raise ValidationError('两次密码不一致'),
   3、源码里
      def _clean_form(self):
        try:
            cleaned_data = self.clean()
        except ValidationError as e:
            self.add_error(None, e)
        else:
            if cleaned_data is not None:
                self.cleaned_data = cleaned_data
                
   self.add_error(None, e)
   错误信息格式:{"__all__":e},不是第一次forms组件校验失败的格式{字段:错误信息}
   所以需要forms.errors.get("__all__"),
   错误信息是个列表:print("error",form.errors.get("__all__")[0])
   
   errors=for m.errors.get("__all__")赋值给模板,{{ errors.0 }}
    def clean(self):
        pwd=self.cleaned_data.get('pwd')
        r_pwd=self.cleaned_data.get('r_pwd')
        
        # 如果第一次密码没输会提示forms验证错误信息, 确认密码执行还会再报错两次密码不一致,
        #  所以先判断有没有 :if pwd and r_pwd:
        if pwd and r_pwd:
            if pwd==r_pwd:
                return self.cleaned_data
            else:
                raise ValidationError('两次密码不一致')
        else:
            return self.cleaned_data

源码位置:

is_valid 
self.errors  
self.full_clean() 
		self._clean_fields()
        self._clean_form()
        self._post_clean()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值