Django组件-forms组件

Posted haowen980

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django组件-forms组件相关的知识,希望对你有一定的参考价值。

 

 

forms组件

django中的Form组件有以下几个功能:

  • 生成html标签
  • 验证用户数据(显示错误信息)
  • HTML Form提交保留上次提交数据
  • 初始化页面显示内容

校验字段功能

之前写的视图函数,提交的数据,没有做校验,就调教到数据库里面了。这样是不对的。

比如:用户名,必须要符合一定的长度。密码复杂度,等等。

forms组件最大的作用,就是做数据校验。

 

普通做法,一个一个写校验规则,没有解耦。校验规则,都在视图函数里面。

新建项目formDemo

新建urls.py ,新增路径index

1 from app01 import views
2 urlpatterns = [
3     path(admin/, admin.site.urls),
4     path(index/, views.index),
5 ]

修改views.py ,新增index视图函数,form组件先放到视图函数

单独起一个类,后续会分离出来

from django.shortcuts import render

# Create your views here.
from django import forms  # 必须导入模块
class DemoForm(forms.Form):  # 必须继承Form
    #限制数据为字符串,最大长度32
    name = forms.CharField(max_length=32)
    age = forms.IntegerField()  # 限制为数字
    email = forms.EmailField()  # 限制为邮箱格式

def index(request):
    return render(request,"index.html")

 templates新增index.html,里面是空的

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

</body>
</html>

打开Pycharm,点击左下角的Django Console

 技术分享图片

输入以下命令,导入视图函数的DemoForm类

from app01.views import DemoForm

 效果如下:

技术分享图片

DemoForm类是用来做校验的,它接收一个字典。字典必须包含2个key,分别是name,age,email

测试一个字典数据

执行下面2个命令

form=DemoForm({"name":"john","age":"21","email":"[email protected]"})
form.is_valid()

效果如下:输出True

技术分享图片

解释:

is_valid()表示执行校验,如果3个key都符合要求,输出True

测试1:age不符合

技术分享图片

3个必须同时成立才行

技术分享图片

在DemoForm里面,等式左边对应的是key,等式右边对应校验规则

它有一个默认规则,不能为空

 

测试2:少一个字段

技术分享图片

从结果上来看,也是可以通过的。

它只校验指定的字段,那么额外的键值,会忽略

 

网页校验

修改urls.py,增加路径addbook

from app01 import views
urlpatterns = [
    path(‘admin/‘, admin.site.urls),
    path(‘index/‘, views.index),
    path(‘addbook/‘, views.addbook),
]

修改views.py,增加addbook视图函数,完整代码如下:

from django.shortcuts import render,HttpResponse

# Create your views here.
from django import forms
class DemoForm(forms.Form):
    name = forms.CharField(max_length=32)
    age = forms.IntegerField()
    email = forms.EmailField()
class UserForm(forms.Form):
    #限制数据为字符串,最小长度4,最大长度12
    name = forms.CharField(min_length=4,max_length=12)
    age = forms.IntegerField()  #限制为数字
    #限制长度为11位
    tel = forms.CharField(min_length=11,max_length=11)


def index(request):

    return render(request,"index.html")

def addbook(request):
    if request.method == "POST":
        #将post数据传给UserForm
        form = UserForm(request.POST)
        if forms.is_valid():    #验证数据
            print("success")
        else:
            print("fail")
        return HttpResponse("ok")
    
    return render(request,"addbook.html")

templates新增addbook.html

做表单校验的时候,一定要注意,表单的name和class的属性必须一一对应

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h3>添加用户</h3>
<form action="" method="post">
    {% csrf_token %}
    <lable>姓名</lable><input type="text" name="name"/><br/>
    <lable>年龄</lable><input type="text" name="age"/><br/>
    <lable>邮箱</lable><input type="text" name="email"/><br/>
    <lable>手机号码</lable><input type="text" name="tel"/>
    <br/>
    <input type="submit">
</form>
</body>
</html>

 网页访问添加页面,输出信息

技术分享图片

提交之后

技术分享图片

控制台输出:

技术分享图片

 

 

空表单直接提交

技术分享图片

Pycharm控制台输出:fail

 

is_valid()

form.is_valid() 它做了2件事情:

1.将数据传给form

2.将验证数据拆分到2个容器中

self.cleandtate={}表示干净的数据

self.error = {}表示验证不通过的数据

self表示UserForm类的实例对象


addbook视图函数

def addbook(request):
    if request.method == "POST":
        print(request.POST)
        # 将post数据传给UserForm
        form = UserForm(request.POST)
        if form.is_valid():  # 验证数据
            print("###success###")
            print(form.cleaned_data)
            print(form.errors)
        else:
            print("###fail###")
            print(form.cleaned_data)
            print(form.errors)
            print(type(form.errors))

        return HttpResponse("ok")

    return render(request,"addbook.html")

 再次提交数据

 技术分享图片

 Pycharm控制台输出:

 技术分享图片

虽然POST发送了5个键值,但是UserForm只校验3个键值。

form.cleaned_data 输出了3个键值

form.errors 输出的内容空,它的类型为ErrorDict

只要有一个错误,就会走else 

  

 

错误数据演示

修改views.py,修改UserForm,增加邮箱

技术分享图片
class UserForm(forms.Form):
    #限制数据为字符串,最小长度4,最大长度12
    name = forms.CharField(min_length=4,max_length=12)
    age = forms.IntegerField()  #限制为数字
    email = forms.EmailField()  #限制为邮箱格式
    #限制长度为11位
    tel = forms.CharField(min_length=11,max_length=11)
views.py

输入一个错误的表单

技术分享图片

Pycharm控制台输出:

技术分享图片

form.errors输出了一段Html标签,提示邮箱格式错误

提取email错误信息

修改UserForm

def addbook(request):
    if request.method == "POST":
        # 将post数据传给UserForm
        form = UserForm(request.POST)
        print(request.POST)
        if form.is_valid():  # 验证数据
            print("###success###")
            print(form.cleaned_data)  # 所有干净的字段以及对应的值
            # ErrorDict : {"校验错误的字段":["错误信息",]}
            print(form.errors)
            print(type(form.errors))  # 打印
        else:
            print("###fail###")
            print(form.cleaned_data)
            print(form.errors)
            # 获取email错误信息,返回一个错误列表,可以切片
            print(form.errors.get("email"))
            # 获取第一个错误信息
            print(form.errors.get("email")[0])

        return HttpResponse("ok")

    return render(request,"addbook.html")

 pycharm控制台输出

技术分享图片

form.errors.get("email") 可以提取email的错误信息,它返回的是一个错误列表

通过切片,可以获取第一个错误信息

渲染标签功能

渲染方式1

使用自带的模板属性渲染

上面讲的form表单里面的元素,是手动写的。form组件可以帮你实现渲染表单元素!

那么需要渲染哪些元素,取决于UserForm这个自定义类的属性来决定的

举例:

修改addbook视图函数

def addbook(request):
    if request.method == "POST":
        # 将post数据传给UserForm
        form = UserForm(request.POST)
        print(request.POST)
        if form.is_valid():  # 验证数据
            print("###success###")
            print(form.cleaned_data)  # 所有干净的字段以及对应的值
            # ErrorDict : {"校验错误的字段":["错误信息",]}
            print(form.errors)
            print(type(form.errors))  # 打印
        else:
            print("###fail###")
            print(form.cleaned_data)
            print(form.errors)
            # 获取email错误信息,返回一个错误列表,可以切片
            print(form.errors.get("email"))
            # 获取第一个错误信息
            print(form.errors.get("email")[0])

        return render(request, "adduser.html", {"form":form})

    else:
        form = UserForm()
        return render(request,"addbook.html",{"form":form})

  修改addbook.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h3>添加用户</h3>
<form action="" method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <br/>
    <input type="submit">
</form>
</body>
</html>

as_p是一个特殊的属性,常见的有:

  • {{ form.as_table }} 以表格的形式将它们渲染在<tr> 标签中
  • {{ form.as_p }} 将它们渲染在<p> 标签中
  • {{ form.as_ul }} 将它们渲染在<li> 标签中

 访问页面,效果如下:

技术分享图片

 

使用浏览器工具,查看html代码

它使用了P标签来包裹

技术分享图片

 laber的for属性和input的id属性是对应的。id的名字和UserForm类定义的属性是类似的,加了id_前缀。

 lable的显示的文字和UserForm类定义的属性是一样的,首字母大写了!

 

input的name属性和UserForm类定义的属性是一样的

默认自带required属性,不允许内容为空。

minlength的属性来源于UserForm类的定义。

注意:form组件只能渲染表单里面的元素,比如input标签。除此之外,其他的需要手写!

它的样式,太丑了!

渲染方式2

使用自定义的标签来包裹form变量

举例:

更改addbook.html

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h3>添加用户</h3>
<form action="" method="post">
    {% csrf_token %}
    <div>
        <p>姓名</p>
        {{ form.name }}
    </div>
    <div>
        <p>年龄</p>
        {{ form.age }}
    </div>
    <div>
        <p>邮箱</p>
        {{ form.email }}
    </div>
    <div>
        <p>手机号码</p>
        {{ form.tel }}
    </div>
    <input type="submit">
</form>
</body>
</html>

  

刷新页面效果如下:

技术分享图片

 

渲染方式3

使用for循环渲染

修改addbook.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h3>添加用户</h3>
<form action="" method="post">
    {% csrf_token %}
    {% for field in form %}
        <div>
            <label for=""> {{ field.label }}</label>
            {{ field }}
        </div>
    {% endfor %}
    <input type="submit">
</form>
</body>
</html>

刷新网页,效果如下:

技术分享图片

field.label 表示属性名

field 表示input输入框

显示中文

将label换成中文,需要增加label属性

修改views.py里面的UserForm类

1 class UserForm(forms.Form):  # 必须继承Form
2     #限制数据为字符串,最小长度4,最大长度12
3     name = forms.CharField(min_length=4,max_length=12,label="姓名")
4     age = forms.IntegerField(label="年龄")  # 限制为数字
5     email = forms.EmailField(label="邮箱")  # 限制为邮箱格式
6     #限制长度为11位
7     tel = forms.CharField(min_length=11,max_length=11,label="手机号码")

刷新网页,效果如下:

技术分享图片

 美化input输入框

需要使用bootstrap

修改urls.py,修改路径、

urlpatterns = [
    path(‘admin/‘, admin.site.urls),
    path(‘index/‘, views.index),
    path(‘adduser/‘, views.adduser),
]

修改views.py,将addbook重名为adduser

def adduser(request):
    if request.method == "POST":
        # 将post数据传给UserForm
        form = UserForm(request.POST)
        print(request.POST)
        if form.is_valid():  # 验证数据
            print("###success###")
            print(form.cleaned_data)  # 所有干净的字段以及对应的值
            # ErrorDict : {"校验错误的字段":["错误信息",]}
            print(form.errors)
            print(type(form.errors))  # 打印
        else:
            print("###fail###")
            print(form.cleaned_data)
            print(form.errors)
            # 获取email错误信息,返回一个错误列表,可以切片
            print(form.errors.get("email"))
            # 获取第一个错误信息
            print(form.errors.get("email")[0])

        return render(request, "adduser.html", {"form":form})

    else:
        form = UserForm()
        return render(request,"adduser.html",{"form":form})

将addbook.html,重命名为adduser.html

引入bootstrap,代码如下:

访问url: http://127.0.0.1:8000/adduser/

效果如下:

 技术分享图片

这里面input用的还是默认样式,只要给input标签增加class="form-group",就有美化效果!

由于input是form组件渲染的,不能直接添加class,需要在UserForm类里面,指定class

修改UserForm类之前,导入一个模块widgets

Widgets

widget 是Django 对HTML输入元素的表示。Widget 负责渲染HTML和提取GET/POST 字典中的数据。

如果你想让某个Widget 实例与其它Widget 看上去不一样,你需要在Widget 对象实例化并赋值给一个表单字段时指定额外的属性(以及可能需要在你的CSS 文件中添加一些规则)

修改views.py,完整代码如下:

 

  

  

  

 

  

 

 

 

 


以上是关于Django组件-forms组件的主要内容,如果未能解决你的问题,请参考以下文章

Django 框架篇: Django中的Form 组件

Django—分页器与form组件

Django框架之Form组件

Django自带序列化组件;分页器;Forms组件

Django Form 组件

Django高级-Form表单组件应用