Django 8.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>


urls

from app01 import views
urlpatterns = [
    path('admin/', admin.site.urls),
    path('reg/', views.reg),
]

(form组件)定义规则

 

注意

 

 总结校验字段功能

1、模板层form表单的name=‘属性值’必须与 form组件字段名称一致

2、定义class UserForm(forms.Form)

3、对前段传来的数据进行验证:form=UserForm(request.POST)

4、判断验证是否成功,布尔值form.is_valid()

5、print(form.cleaned_data)# 存放匹配成功的键值对  print(form.errors) # 存放 键:失败的信息

 

 

2.渲染标签

reg.html

方式一

views

from django.shortcuts import render, HttpResponse
from django import forms   # 导入forms组件
# 定义校验规则
class UserForm(forms.Form):
    name = forms.CharField(min_length=4, max_length=10)
    pwd = forms.CharField(min_length=4)
    re_pwd = forms.CharField(min_length=4)
    email = forms.EmailField()
    tel = forms.CharField()
def reg_html(request):
    form = UserForm()
    return render(request, 'reg_html.html', locals())

reg.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h3>渲染标签功能1</h3>
    <form action="" method="post">
        {% csrf_token %}
        <p>用户名
            {{ form.user }}
        </p>
        <p>密码{{ form.pwd }}</p>
        <p>确认密码{{ form.re_pwd}}</p>
        <p>电话{{ form.tel }}</p>
        <p>邮箱{{ form.email }}</p>
        <input type="submit">
    </form>
</body> </html>
可实现相同的功能

  

 

方式二

 reg.html

<h3>渲染方式2</h3>
   <form action="" method="post">
        {% csrf_token %}
        {% for field in form %}
        <div>
            {{ field.label }}
            {{ field }}
        </div>
        {% endfor %}
    </form>

可以自己设置label属性

 

方式3

<h3>渲染方式3</h3>
<form action="" method="post">
    {% csrf_token %}
    {{ form.as_p }}
     <input type="submit">
</form>

 

3、显示error与重置输入信息功能

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

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

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

 

 reg.html

<h3>渲染标签方式1</h3>
    <form action="" method="post" novalidate>
        {% csrf_token %}
        <p> {{ form.user.label }}
            {{ form.user }}<span>{{ form.user.errors.0 }}</span> //有错误信息就放,没有就不显示
        </p>
        <p>{{ form.pwd.label }}{{ form.pwd }} <span>{{ form.pwd.errors.0 }}</span></p> //这里放错误信息,它自己的errors
      <p>{{ form.re_pwd.label }}{{ form.re_pwd}}<span>{{ form.re_pwd.errors.0 }}</span></p>
        <p>{{ form.tel.label }}{{ form.tel }}<span>{{ form.tel.errors.0 }}</span></p>
        <p>{{ form.email.label }}{{ form.email }}<span>{{ form.email.errors.0 }}</span></p>
        <input type="submit">
    </form>

views.py 

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) print(request.POST) form=UserForm(request.POST)
  #只要能传来这样一个字典,字典对应的键和值;键能跟它的字段匹配上,就可以做校验;前端的form表单的name属性值应该与forms组件字段名称一致。
  #你这个form已经通过验证传一个个数据了;已绑定数据表单对象的form
print(form.is_valid()) # 返回布尔值 通过校验之后的form if form.is_valid(): #如果都正确           经过验证之后的form print(form.cleaned_data)  #这是全部都是对的 返回字典 return HttpResponse('ok') else: print(form.cleaned_data)# 存放匹配成功的键值对 print(form.errors) # 存放 键:失败的信息
       #  如果if语句中所有字段都校验成功,则form中的form.cleaned_data{}属性保存了所有正确的键值 
                                                    form.errors放的是所有错误信息列表 return render(request, 'reg.html', locals()) form=UserForm()  #未绑定数据表单对象,上边的form是绑定表单对象 
             #这个form跟上边那个form = UserForm(request.POST) 是不一个form;上边的form即使验证失败了它会给你保留你输入的values值
return render(request, 'reg.html', locals()) #把值传进来进行渲染;get请求

  

说明:

4、forms组件的参数配置

  1)、参数提示参数设置

views.py

from django.forms import widgets
## 定义校验规则
class UserForm(forms.Form):
    # min_length最低为4位
    user=forms.CharField(min_length=4,label='用户名'
                         ,error_messages={'required':'该字段不为空', 'min_length': '不能少于4个字符'},

                         widget=widgets.TextInput(attrs={'class':'form-control'}))# 默认lable=User
    pwd=forms.CharField(min_length=4,label='密码',widget=widgets.PasswordInput(attrs={'class': 'form-control'})
                        )
    re_pwd=forms.CharField(min_length=4,label='确认密码',widget=widgets.PasswordInput(attrs={'class': 'form-control'}))
    email=forms.EmailField(label='邮箱',widget=widgets.EmailInput(attrs={'class': 'form-control'})
                           , error_messages={'invalid': '格式错误'})
    tel=forms.CharField(label='电话',widget=widgets.NumberInput(attrs={'class': 'form-control'}))

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":"alex", 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())

  

2)、引入bootstrap模块优化界面

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">
{#            <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 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>

{#            <h3>forms组件渲染方式2</h3>#}
{#            <form action="" method="post">#}
{#                {% csrf_token %}#}
{#                {% for field in form %}#}
{#                    <p>#}
{#                        <label for="">{{ field.label }}</label>#}
{#                        {{ field }}#}
{#                    </p>#}
{#                {% endfor %}#}
{#                <input type="submit">#}
{#            </form>#}
{#            #}
{#            <h3>forms组件渲染方式3</h3>#}
{#            <form action="" method="post">  {# 不灵活,把样式给固定死了#}
{#                {% csrf_token %}#}
{#                {{ form.as_p }}#}
{#                <input type="submit">#}
{#            </form>#}

        </div>
    </div>
</div>
</body>
</html>

  

 

5、forms组件的局部钩子

views

from django import forms

from django.forms import widgets
from app01.models import UserInfo
from django.core.exceptions import ValidationError  # 导入验证错误
## 定义校验规则
class UserForm(forms.Form):
    # min_length最低为4位
    user=forms.CharField(min_length=4,label='用户名'
                         ,error_messages={'required':'该字段不为空', 'min_length': '不能少于4个字符'},

                         widget=widgets.TextInput(attrs={'class':'form-control'}))# 默认lable=User
    pwd=forms.CharField(min_length=4,label='密码',widget=widgets.PasswordInput(attrs={'class': 'form-control'})
                        )
    re_pwd=forms.CharField(min_length=4,label='确认密码',widget=widgets.PasswordInput(attrs={'class': 'form-control'}))
    email=forms.EmailField(label='邮箱',widget=widgets.EmailInput(attrs={'class': 'form-control'})
                           , error_messages={'invalid': '格式错误'})
    tel=forms.CharField(label='电话',widget=widgets.NumberInput(attrs={'class': 'form-control'}))

    # 局部钩子
    def clean_user(self):
        val=self.cleaned_data.get('user') #拿到上边字段第一次校验的

        ret=UserInfo.objects.filter(useranme=val)# 第二次校验(局部校验)数据库中的user
        if not ret:
            return ret
        else:
            raise ValidationError('该用户已经注册')  # 抛出验证错误

def reg(request):
    if request.method=='POST':
        print(request)
        print(request.POST)
        form=UserForm(request.POST)
        print(form.is_valid()) # 返回布尔值
        if form.is_valid():
            print(form.cleaned_data)
            return HttpResponse('ok')
        else:
            print(form.cleaned_data)# 存放匹配成功的键值对
            print(form.errors)      # 存放 键:失败的信息
            return render(request, 'reg.html', locals())

    form=UserForm()
    return render(request, 'reg.html', locals())

  提交与数据库姓名重名的结果

在模板层加样式属性,让错误信息显示颜色

<span style="color: red">{{ form.pwd.errors.0 }}</span>

6.全局钩子校验

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

myforms.py

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>

  

posted @ 2019-03-05 10:56  李卓航  阅读(152)  评论(0编辑  收藏  举报