8.Django-form组件

 

1.form组件的校验功能

文件formsdemo

models

from django.db import models

# Create your models here.
class UserInfo(models.Model):
    name=models.CharField(max_length=32)
    pwd=models.CharField(max_length=32)
    email=models.EmailField()
    tel=models.CharField(max_length=32)

views

from django.shortcuts import render, HttpResponse

# Create your views here.

from django import forms
class UserForm(forms.Form):   #创建form组件就是这个类,名字任意叫;定义的规则可以多写(多的忽略那你)不能少写
    name = forms.CharField(min_length=4)
    pwd = forms.CharField(min_length=4)
    r_pwd = forms.CharField(min_length=4)
    email = forms.EmailField()
    tel = forms.CharField   #forms组件的键的名字和这些字段的名字要一致


def reg(request):
    if request.method == "POST":
        print(request.POST)
#<QueryDict: {'csrfmiddlewaretoken': ['gEVJ683XmW6CKzXzfYDNGLXPuURgOjka6yYUuxGVBp9n1tV78D2APZ1iktJmXKq8'], 'name': ['kris'], 'pwd': ['123'], 'r_pwd': ['123'], 'email': ['1234@qq.com'], 'tel': ['18271182769']}>

        #form = UserForm({"name":"yu", "email":"123@qq.com", "xxx":"alex" })  #类的实例化,可以给它传参,只会给你校验字段里边有的数值,没有的不会校验,有的校验完后就会返回True;form组件的校验规则是有几个就要写几个,多了无所谓不能少写,而且传来的也要符合字段规则。
        form = UserForm(request.POST)  #只要能传来这样一个字典,字典对应的键和值;键能跟它的字段匹配上,就可以做校验;前端的form表单的name属性值应该与forms组件字段名称一致。
    
        print(form.is_valid())  #返回一个布尔值,只会返回 True or False 
        if form.is_valid(): #都正确
            print(form.cleaned_data)   #这是全部都是对的键值对{"name":"kris", "email":"123@qq.com"...}
        else:
            # print(form.cleaned_data) #这是两个字典.这里放正确的{"email":"123@qq.com"}
            # print(form.errors)       #这里放错误的 {"name":["......."]}(如果name校验错了)
   ##<ul class="errorlist"><li>name<ul class="errorlist"><li>该用户已注册</li></ul></li><li>pwd<ul class="errorlist"><li>Ensure this value has at least 4 characters (it has 3).</li></ul></li><li>r_pwd<ul class="errorlist"><li>Ensure this value has at least 4 characters (it has 3).</li></ul></li></ul> # print(type(form.errors)) #ErrorDict <class 'django.forms.utils.ErrorDict'> print(form.errors.get("name")) #<ul class="errorlist"><li>该用户已注册</li></ul> print(type(form.errors.get("name"))) #ErrorDict <class 'django.forms.utils.ErrorList'> print(form.errors.get("name")[0]) 该用户已注册 ''' if 所有字段校验成功,则
      form.is_valid()
      form.cleaned_data:{"name":"kris", "email":"123@qq.com"} 校验都通过之后,所有字段的信息都在这里边。
      form.errors
''' return HttpResponse("OK") return render(request, "reg.html") #这是get请求

reg.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="" method="post">
        {% csrf_token %}
        <p>用户名<input type="text" name="name"></p>
        <p>密码<input type="password" name="pwd"></p>
        <p>确认密码<input type="password" name="r_pwd"></p>
        <p>邮箱<input type="text" name="email"></p>
        <p>手机号<input type="text" name="tel"></p>

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

2.渲染标签

reg.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="" method="post">
        {% csrf_token %}
        <p>用户名<input type="text" name="name"></p>
        <p>密码<input type="password" name="pwd"></p>
        <p>确认密码<input type="password" name="r_pwd"></p>
        <p>邮箱<input type="text" name="email"></p>
        <p>手机号<input type="text" name="tel"></p>

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

    <hr>  //
    <h3>forms组件的渲染方式1</h3>  //form表单的name值,应该与forms组件的字段的名字一致;django的forms组件怕你写的不一致,这里才有了渲染的功能;是get请求的时候
    <form action="" method="post">
        {% csrf_token %}
        <p>{{ form.name.label }}
            {{ form.name }}
        </p>
        <p>
            {{ form.pwd.label }}
            {{ form.pwd }}
        </p>
        <p>
            确认密码
            {{ form.r_pwd }}
        </p>
        <p>邮箱{{ form.email }}</p>
        <p>手机号{{ form.tel }}</p>
        <input type="submit">
    </form>

    <h3>forms组件渲染方式2</h3>  // 渲染出来的是英文,可以在UserForm这个类里边的字段下添加 label标签写上中文
    <form action="" method="post">
        {% csrf_token %}
        {% for field in form %}   //for循环这个form;拿到这个field(每个字段对象,等同与上面方式一的form.name、form.pwd...            <p>
                <label for="">{{ field.label }}</label>  //每个字段里边加上自己label就可以了,label标签可以跟下面的关联起来。
                {{ field }}
            </p>
        {% endfor %}
        <input type="submit">
    </form>

    <h3>forms组件渲染方式3</h3>
   <form action="" method="post">  {# 不灵活,把样式给固定死了,p标签里边放label标签 #}
        {% csrf_token %}
        {{ form.as_p }}   //调用它下面as_p的方法,它还有as_ul的方法;
        <input type="submit">
    </form>
</body>
</html>

渲染错误信息

第一个form通过验证已经有一个个的数据了,区别在于它传到reg.html时候,它.name还是input标签,你点提交这个页面没有变;同时它也可以把你传的那个信息给渲染出来作为input标签的value值。

之所以能看到错误信息,是因为我post提交了构建了一个新form页面,在post请求下加了下面这个:

 return render(request, "reg.html", locals()) 

reg.html

    <h3>forms组件的渲染方式1</h3>
    <form action="" method="post" novalidate>
        {% 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>  {#这里放错误信息,它自己的errors#}
        </p>
        <p>
            确认密码
            {{ form.r_pwd }}<span>{{ form.r_pwd.errors.0 }}</span>
        </p>
        <p>邮箱{{ form.email }}<span>{{ form.email.errors.0 }}</span></p>
        <p>手机号{{ form.tel }}<span>{{ form.tel.errors.0 }}</span></p>
        <input type="submit">
    </form>

views

from django.shortcuts import render, HttpResponse

# Create your views here.

from django import forms
class UserForm(forms.Form):   #创建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="手机号")


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


        #form = UserForm({"name":"yu", "email":"123@qq.com"})  #类的实例化,可以给它传参
        form = UserForm(request.POST)  #只要能传来这样一个字典,字典对应的键和值;键能跟它的字段匹配上,就可以做校验;前端的form表单的name属性值应该与forms组件字段名称一致。
            #你这个form已经通过验证传一个个数据了;已绑定数据表单对象的form
        print(form.is_valid())  #返回一个布尔值 通过校验之后的form
        if form.is_valid(): #都正确           经过验证之后的form
            print(form.cleaned_data)   #这是全部都是对的{"name":"kris", "email":"123@qq.com"}
        else:
            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"))) #ErrorDict
            # print(form.errors.get("name")[0])
            return render(request, "reg.html", locals())  #如果校验失败后,它返回这个页面,可以把第一次输入的信息给保存了,作为value值;它走的是post请求
        ''' 之所以post提交后可以保存输入的信息,因为这两个form不是一个
        if 所有字段校验成功,则form.cleaned_data:{"name":"kris", "email":"123@qq.com"}
        '''

        #return HttpResponse("OK")  get请求是走下面这个
    form=UserForm()  #未绑定数据表单对象,上边的form是绑定表单对象 #这个form跟上边那个form = UserForm(request.POST) 是不一个form;上边的form即使验证失败了它会给你保留你输入的values值
    return render(request, "reg.html", locals()) #把值传进来进行渲染;get请求

3.forms组件的参数配置

reg.html

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6     <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
 7     <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
 8 </head>
 9 <body>
10 <div class="container">
11     <div class="row">
12         <div class="col-md-6 col-lg-offset-3">
13 {#            <form action="" method="post">#}
14 {#                {% csrf_token %}#}
15 {#                <p>用户名<input type="text" name="name"></p>#}
16 {#                <p>密码<input type="password" name="pwd"></p>#}
17 {#                <p>确认密码<input type="password" name="r_pwd"></p>#}
18 {#                <p>邮箱<input type="text" name="email"></p>#}
19 {#                <p>手机号<input type="text" name="tel"></p>#}
20 {#        #}
21 {#                <input type="submit">#}
22 {#            </form>#}
23 
24             <hr>
25             <h3>forms组件的渲染方式1</h3>
26             <form action="" method="post" novalidate>
27                 {% csrf_token %}
28                 <p>{{ form.name.label }}
29                     {{ form.name }}<span>{{ form.name.errors.0 }}</span>
30                 </p>
31                 <p>
32                     {{ form.pwd.label }}
33                    {{ form.pwd }}<span>{{ form.pwd.errors.0 }}</span>  {#这里放错误信息,它自己的errors#}
34                 </p>
35                 <p>
36                     确认密码
37                     {{ form.r_pwd }}<span>{{ form.r_pwd.errors.0 }}</span>
38                 </p>
39                 <p>邮箱{{ form.email }}<span>{{ form.email.errors.0 }}</span></p>
40                 <p>手机号{{ form.tel }}<span>{{ form.tel.errors.0 }}</span></p>
41                 <input type="submit">
42             </form>
43 
44 {#            <h3>forms组件渲染方式2</h3>#}
45 {#            <form action="" method="post">#}
46 {#                {% csrf_token %}#}
47 {#                {% for field in form %}#}
48 {#                    <p>#}
49 {#                        <label for="">{{ field.label }}</label>#}
50 {#                        {{ field }}#}
51 {#                    </p>#}
52 {#                {% endfor %}#}
53 {#                <input type="submit">#}
54 {#            </form>#}
55 {#            #}
56 {#            <h3>forms组件渲染方式3</h3>#}
57 {#            <form action="" method="post">  {# 不灵活,把样式给固定死了#}
58 {#                {% csrf_token %}#}
59 {#                {{ form.as_p }}#}
60 {#                <input type="submit">#}
61 {#            </form>#}
62 
63         </div>
64     </div>
65 </div>
66 </body>
67 </html>
View Code

views

 1 from django.shortcuts import render, HttpResponse
 2 
 3 # Create your views here.
 4 
 5 from django import forms
 6 
 7 from django.forms import widgets
 8 class UserForm(forms.Form):   #创建form组件就是这个类,名字任意叫;定义的规则可以多写(多的忽略那你)不能少写
 9     name = forms.CharField(min_length=4, label="用户名",error_messages={"required":"该字段不能为空"},
10                            widget=widgets.TextInput(attrs={"class":"form-control"})
11                             )
12     pwd = forms.CharField(min_length=4, label="密码",
13                           widget=widgets.PasswordInput(attrs={"class":"form-control"}))
14     r_pwd = forms.CharField(min_length=4,label="确认密码",error_messages={"required":"该字段不能为空"},widget=widgets.TextInput(attrs={"class":"form-control"}))
15     email = forms.EmailField(label="邮箱",error_messages={"required":"该字段不能为空","invalid":"格式错误"},widget=widgets.TextInput(attrs={"class":"form-control"}))
16     tel = forms.CharField(label="手机号",widget=widgets.TextInput(attrs={"class":"form-control"}))
17 
18 
19 def reg(request):
20     if request.method == "POST":
21         print(request.POST)
22 
23 
24         #form = UserForm({"name":"yu", "email":"123@qq.com"})  #类的实例化,可以给它传参
25         form = UserForm(request.POST)  #只要能传来这样一个字典,字典对应的键和值;键能跟它的字段匹配上,就可以做校验;前端的form表单的name属性值应该与forms组件字段名称一致。
26             #你这个form已经通过验证传一个个数据了;已绑定数据表单对象
27         print(form.is_valid())  #返回一个布尔值
28         if form.is_valid(): #都正确
29             print(form.cleaned_data)   #这是全部都是对的{"name":"kris", "email":"123@qq.com"}
30         else:
31             print(form.cleaned_data) #这是两个字典.这里放正确的{"email":"123@qq.com"}
32             # print(form.errors)  #这里放错误的 {"name":["......."]}
33             # print(type(form.errors)) #ErrorDict
34 
35             # print(form.errors.get("name"))
36             # print(type(form.errors.get("name"))) #ErrorDict
37             # print(form.errors.get("name")[0])
38             return render(request, "reg.html", locals())  #如果校验失败后,它返回这个页面
39         '''
40         if 所有字段校验成功,则form.cleaned_data:{"name":"kris", "email":"123@qq.com"}
41         '''
42 
43         #return HttpResponse("OK")
44     form=UserForm  #未绑定数据表单对象 #这个form跟上边那个form = UserForm(request.POST) 是不一个form;上边的form即使验证失败了它会给你保留你输入的values值
45     return render(request, "reg.html", locals())
View Code
from django.forms import widgets
class UserForm(forms.Form):   #创建form组件就是这个类,名字任意叫;定义的规则可以多写(多的忽略那你)不能少写
    name = forms.CharField(min_length=4, label="用户名",error_messages={"required":"该字段不能为空"}, //错误信息,required是为空错误
                           widget=widgets.TextInput(attrs={"class":"form-control"})  #渲染什么标签通过这里告诉我,这个标签有什么属性通过attrs告诉我,form-control样式就变好看了
                            ) //它默认的就是TextInput类型
    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"}))

4.forms组件校验的局部钩子

views

from django import forms

from django.forms import widgets
from app01.models import UserInfo
from django.core.exceptions import NON_FIELD_ERRORS,ValidationError
class UserForm(forms.Form):   #创建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):   #限定手机号11位 
        val = self.cleaned_data.get("tel")
        if len(val)==11:
            return val
        else:
            raise ValidationError("手机号格式错误")

 

 5.全局钩子

 forms可单独放在一个py文件里边

myforms.py

#Author:Kris

from django import forms

from django.forms import widgets
from app01.models import UserInfo
from django.core.exceptions import NON_FIELD_ERRORS,ValidationError
class UserForm(forms.Form):   #创建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")  #说明它通过上边name字段那层的校验了
        ret = UserInfo.objects.filter(name=val) 
        if not ret:
            return val  #再校验,合格了返回的还是之前的那个val
        else:
            raise ValidationError("该用户已注册")
    def clean_tel(self):
        val = self.cleaned_data.get("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 and r_pwd:
            if pwd == r_pwd:
                return self.cleaned_data
            else: 
                raise ValidationError('两次密码不一致')
        else:  #如果pwd和r_pwd有一个为空,说明没检验通过
            return self.cleaned_data

views

from django.shortcuts import render, HttpResponse

# Create your views here.

from app01.myforms import *
def reg(request):
    if request.method == "POST":
        print(request.POST)
        #form = UserForm({"name":"yu", "email":"123@qq.com"})  #类的实例化,可以给它传参
        form = UserForm(request.POST)  #只要能传来这样一个字典,字典对应的键和值;键能跟它的字段匹配上,就可以做校验;前端的form表单的name属性值应该与forms组件字段名称一致。
            #你这个form已经通过验证传一个个数据了;已绑定数据表单对象
        print(form.is_valid())  #返回一个布尔值
        if form.is_valid(): #都正确;is_valid帮我们做校验的方法
            print(form.cleaned_data)   #这是全部都是对的{"name":"kris", "email":"123@qq.com"}
        else:
            print(form.cleaned_data) #这是两个字典.这里放正确的{"email":"123@qq.com"}

            #全局钩子错误
            #print('errors', form.errors.get('__all__')[0])  #可以写某个字段 --->> 打印: error 两次密码不一致
            errors = form.errors.get('__all__') #有name、email字段错了就写name、email,全局错误就写__all__ ;拿到errors交给模板

            return render(request, "reg.html", locals())  #如果校验失败后,它返回这个页面
        '''
        if 所有字段校验成功,则form.cleaned_data:{"name":"kris", "email":"123@qq.com"}
        '''

        #return HttpResponse("OK")
    form=UserForm()  #未绑定数据表单对象 #这个form跟上边那个form = UserForm(request.POST) 是不一个form;上边的form即使验证失败了它会给你保留你输入的values值
    return render(request, "reg.html", locals())

reg.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-6 col-lg-offset-3">

            <hr>
            <h3>forms组件的渲染方式1</h3>
            <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>  {#这里放错误信息,它自己的errors#}
                </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>

        </div>
    </div>
</div>
</body>
</html>
原文地址:https://www.cnblogs.com/shengyang17/p/9126170.html