Django--组件--forms(1)-介绍&使用语法&注册案例

一:引言

1:为何了解forms组件?

顾名思义,forms组件是否是和前端form标签有关系呢?对,能够这么想。html

当咱们在注册网页的时候是否是须要校验数据呢?就以下图。固然注册不符合规则是否是得有提醒,所以须要在页面中显示错误信息提示。前端

而其实这个底层过程是很复杂的,你想若是是你写的代码,你是否是得先对这些字段先取值,以后是否是得按不一样规则一一校验。校验完后成功到无所谓,若错误是否是得一个一个构建错误信息渲染到模板的相应位置。这个过程是很复杂的。而form组件就是实现这个复杂的过程。python

 

2:forms组件的做用?

(1)校验数据数据库

(2)页面显示错误信息django

(3)渲染页面和重置数据后端

(4)解耦浏览器

 

 二:Forms组件的使用语法

 1:建立规则(建立一个forms类)

通常写在views.py文件里bash

from django import forms
#注意:这里的字段必须和前端页面input标签的name属性以及数据库中的字段保持一致
class UserForm(forms.Form):  #建立校验规则类。,必须继承forms组件类
    name=forms.CharField(min_length=5)
    pwd=forms.IntegerField()
    email=forms.EmailField()

 内置字段:博文服务器

 

2:检验数据

咱们在python console中输入检验网络

>>>from app01.views import BookForm
>>>fm=BookForm({"name":"lilz","pwd":123,"email":"abc"})   #要检验的数据====只校验规定的字段,规定的字段若是全对就是true,不检验其余字段,其余字段就是加进去也没有影响 >>>fm.is_valid()  #查看是否合法,合法返回True(必须先查看是否合法
False

>>>fm.cleaned_data  #查看合法的字段
{'name': 'lilz', 'pwd': '123'} =======字典 >>>fm.errors         #查看不合法的字段
{'email': ['Enter a valid email address.', 'Enter a valid email address.']}

 

 

三:forms组件应用的案例--注册

1:目标-实现校验与页面显示信息的功能

  用户名长度不能低于5位

  密码必须是纯数字

  邮箱必须符合邮箱格式

  若是输入格式有错误,请显示在页面上

2:准备

(1)数据库相关

models.py

from django.db import models

class UserInfo(models.Model):
    user=models.CharField(max_length=32)
    pwd=models.CharField(max_length=32)
    email=models.CharField(max_length=32)

 

====>数据库迁移

python manage.py makemigrations    #同步
python manage.py migrate

3:上代码

(1)前端页面

template/reg.html

<style>
    .error{
        color: red;
        margin-left: 10px;
    }
</style>
<body>
    <form action="" method="post">
        {% csrf_token %}
        <p>用户名:<input type="text"name="user"><span class="error">{{ error.name.0 }}</span></p>
        <p>密码:<input type="password"name="pwd"><span class="error">{{ error.pwd.0 }}</span></p>
        <p>邮箱:<input type="email"name="email"><span class="error">{{ error.email.0 }}</span></p>
        <input type="submit">
    </form>
</body>

 

(2)后端代码

urls.py

from django.contrib import admin
from django.urls import path
from app01 import views

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

 

views.py

定义forms规则

from django import forms
from app01.models import UserInfo
#注意:这里的字段必须和前端页面input标签的name属性以及数据库中的字段保持一致
class UserForm(forms.Form):  #建立校验规则类。,必须继承forms组件类
    name=forms.CharField(min_length=5,error_messages={"required":"该字段不能为空"})#error_messages表示提示错误消息  #required表明为空的错误
    pwd=forms.IntegerField()
    email=forms.EmailField(error_messages={"invalid":"邮箱格式错误"})  #invalid表明格式的错误
def reg(request):
    if request.method=='POST':
        # 数据校验,咱们把数据校验代码不放在这里,解耦 ===UserForm校验规则类
        form=UserForm(request.POST)    #把数据放在规则类里校验
        if form.is_valid():#校验数据
            UserInfo.objects.create(**form.cleaned_data) #符合规则后咱们把数据插入到数据库中,由于数据是字典,因此须要打散
        else:
            # print(form.cleaned_data) #{'pwd': 123, 'email': '250197@qq.com'}
            # print(type(form.cleaned_data))  # <class 'dict'>
            # print(form.errors) #<ul class="errorlist"><li>name<ul class="errorlist"><li>This field is required.</li></ul></li></ul>
            # print(type(form.errors))  #<class 'django.forms.utils.ErrorDict'>   #{"name":["",]}
            # print(type(form.errors.get("name")))  #<class 'django.forms.utils.ErrorList'>   #["",]
            # print(form.errors.get("name")[0])  #name对应的错误信息
            error=form.errors
            return render(request,'reg.html',locals())  #把错误数据渲染到模板
    else:
        return render(request,'reg.html')

 

4:效果

5:分析整个流程

(1)访问http://127.0.0.1:8000/reg/  并输入数据,这是一个get请求,

(2)数据经浏览器以http协议数据封装经网络到达服务器

(3)服务器在wsgi.py中以http协议解封装,经中间件的组件到达urls.py文件找到路径对应的视图函数,执行reg函数,reg函数中检查是get请求返回浏览器注册页面

(4)用户在注册页面输入数据点击提交,这是一个标签按钮,而后通过form标签中的路径访问服务器重复(2)(3)步骤到达reg函数,不过是post请求。

(5)post请求处理代码中调用form规则定义类匹配数据是否合规,若合规则把数据写入到数据库表中,不合则把错误不合规则的数据渲染到前端注册页面,而后把注册页面返回给浏览器

四:forms组件应用的案例--注册--优化

1:目标-实现校验、页面显示信息的、渲染页面和重置数据功能

本案例在上面案例的基础上实现

首先分析下上面的案例的缺陷,缺陷一:前端页面input还须要咱们本身写,这比较麻烦;缺陷二:前端页面输入格式错误,虽然有提示错误,但咱们输入的数据也已经没有了。咱们的目标就是使用forms组件解决这缺陷。

2:须要知识点--实现渲染

方法一:简单但不灵活

前端页面reg.html

 

对于<label>/<input> 对,还有几个输出选项:

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

 

后端view

def reg(request):
    if request.method=='POST':
          pass
    else:
        form=UserForm()  #没有把咱们输入的数据放进去查看是否匹配规则。咱们的目的是把UserForm规则类的字段渲染到页面
        return render(request,'reg.html',locals())    

 

效果:

缺陷:

这种方法把样式写死了,虽然这种方法简单

 


 

方法二:(能实现保留数据,关键点在forms对象渲染)灵活但复杂

 前端页面:

<style>
    .error{
        color: red;
        margin-left: 10px;
    }
</style>
<body>
    <form action="" method="post">
        {% csrf_token %}
        <p>用户名:{{ form.name }}<span class="error">{{ error.name.0 }}</span></p>
        <p>密码:{{ form.pwd }}<span class="error">{{ error.pwd.0 }}</span></p>
        <p>邮箱:{{ form.email }}<span class="error">{{ error.email.0 }}</span></p>
        <input type="submit">
    </form>
</body>

后端view

def reg(request):
    if request.method=='POST':
        # 数据校验,咱们把数据校验代码不放在这里,解耦 ===UserForm校验规则类
        form=UserForm(request.POST)    #把数据放在规则类里校验
        if form.is_valid():#校验数据
            UserInfo.objects.create(**form.cleaned_data) #符合规则后咱们把数据插入到数据库中,由于数据是字典,因此须要打散
        else:
            error=form.errors
            return render(request,'reg.html',locals())  #把错误数据渲染到模板
    else:
        form=UserForm()  #没有把咱们输入的数据放进去查看是否匹配规则。咱们的目的是把UserForm规则类的字段渲染到页面
        return render(request,'reg.html',locals())

 


 

 

现象

针对效果咱们作下面分析

现象分析一:前端出现验证效果

正是由于咱们定义的规则属性加入到了标签内,前端才可以在页面就能够控制匹配规则。这是浏览器的机制。每一个浏览器都有不一样的机制。这样是不靠谱的仍是得用后端的匹配规则机制才行,固然前端有也是不错的。

 那么该如何才能让前端不参与任何校验呢?

下面加入novalidate就可以达到此目的

    <form action="" method="post" novalidate>
        {% csrf_token %}
        <p>用户名:{{ form.name }}<span class="error">{{ error.name.0 }}</span></p>
        <p>密码:{{ form.pwd }}<span class="error">{{ error.pwd.0 }}</span></p>
        <p>邮箱:{{ form.email }}<span class="error">{{ error.email.0 }}</span></p>
        <input type="submit">
    </form>

 

 现象分析二:前端的写过的数据依然保留--重置数据

 

为何会这样呢?咱们来分析下

(1)首先咱们访问http://127.0.0.1:8000/reg/  get请求

(2)到达视图函数因为get请求,form=UserForm()是不带数据的,那么就会返回给浏览器渲染后的reg.html文件。

(3)当咱们输入数据,点击提交按钮时,此时根据

<form action="" method="post">
依然会访问http://127.0.0.1:8000/reg/  

 不过此时是post请求。而这个时候form=UserForm(request.POST)是带着数据的

(4)由于        <p>用户名:{{ form.name }}<span class="error">{{ error.name.0 }}</span></p>  

 {{ form.name }}这个位置没有写死,   就会渲染出原来request.POST中的数据给浏览器

 

 


缺陷:

<p>用户名:{{ form.name }}<span class="error">{{ error.name.0 }}</span></p>    中的  {{ form.name }}  是渲染出来的,那么咱们就没法对它更改样式了。也就是咱们对这个input标签没法更改属性。

 

下面的方法就会解决这个问题====在定义的forms规则类中加属性

from django.forms import widgets   #widgets魔法工具包

class UserForm(forms.Form):  #建立校验规则类。,必须继承forms组件类
    name=forms.CharField(min_length=5,
                         error_messages={"required":"该字段不能为空"},
                         widget=widgets.TextInput(attrs={"class":"from-control"})
                         )   #TextInput表示input标签type=text
########################################################
#关于widget:

 # 每一个表单字段都有一个对应的Widget 类,它对应一个HTML 表单Widget,例如<input type="text">

 # 在大部分状况下,字段都具备一个合理的默认Widget。例如,默认状况下,CharField 具备一个TextInput Widget,它在HTML 中生成一个<input type="text">

 

 或者还有一种给属性添加类的方法:

from django import forms
from django.forms import widgets 
class UserForm(forms.Form):
    user=forms.CharField(min_length=5,label="用户名")
    pwd=forms.CharField(min_length=5,widget=widgets.PasswordInput(),label="密码") #密码须要密文
    r_pwd=forms.CharField(min_length=5,widget=widgets.PasswordInput(),label="确认密码")
    email=forms.EmailField(min_length=5,label="邮箱")

    # class Meta:  #控制UserForm类的元类信息
    def __init__(self, *args, **kwargs):#至关于修改forms类的__init__方法
        super().__init__(*args, **kwargs)  #走父类的这个方法
        for filed in self.fields.values():  #循环每一个字段对象
            filed.widget.attrs.update({'class': 'form-control'})  #对每一个属性添加一个类

 

 

 

方法三:

后端:

规则类

class UserForm(forms.Form):  #建立校验规则类。,必须继承forms组件类
    name=forms.CharField(min_length=5,label="用户名")   
    pwd=forms.IntegerField(label="密码")
    email=forms.EmailField(label="邮箱")

 

views---没有变更

def reg(request):
    if request.method=='POST':
        # 数据校验,咱们把数据校验代码不放在这里,解耦 ===UserForm校验规则类
        form=UserForm(request.POST)    #把数据放在规则类里校验
        if form.is_valid():#校验数据
            UserInfo.objects.create(**form.cleaned_data) #符合规则后咱们把数据插入到数据库中,由于数据是字典,因此须要打散
        else:

            error=form.errors
            return render(request,'reg.html',locals())  #把错误数据渲染到模板
    else:
        form=UserForm()  #没有把咱们输入的数据放进去查看是否匹配规则。咱们的目的是把UserForm规则类的字段渲染到页面
        return render(request,'reg.html',locals())
View Code

 

前端页面

<style>
    .error{
        color: red;
        margin-left: 10px;
    }
</style>
<body>
    <form action="" method="post" novalidate>
        {% csrf_token %}
        {% for field in form %} <div>
            <label for="">{{ field.label }}</label> {# 显示字段名:#} {{ field }}{# 显示input框:#} <span class="error">{{ field.errors }}</span> {# 显示错误信息:#} </div> {% endfor %} <input type="submit">
    </form>
</body>

 

效果:

 


 

参考:

配齐博文

Yuan先生

相关文章
相关标签/搜索