欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Django之form组件

程序员文章站 2022-04-25 15:18:03
...

一、form大白话介绍

1.渲染标签

2.校验数据

3.渲染信息

1.渲染标签
# 先产生一个空的类对象
from_obj = MyRegFrom()
# 将该对象传递给html页面  页面上借助与form_obj有三种渲染方式:详细见目录

二、普通方式手写注册功能

views.py

# 注册
def register(request):
    error_msg = ""
    if request.method == "POST":
        username = request.POST.get("name")
        pwd = request.POST.get("pwd")
        # 对注册信息做校验
        if len(username) < 6:
            # 用户长度小于6位
            error_msg = "用户名长度不能小于6位"
        else:
            # 将用户名和密码存到数据库
            return HttpResponse("注册成功")
    return render(request, "register.html", {"error_msg": error_msg})

register.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册页面</title>
</head>
<body>
<form action="/reg/" method="post">
    {% csrf_token %}
    <p>
        用户名:
        <input type="text" name="name">
    </p>
    <p>
        密码:
        <input type="password" name="pwd">
    </p>
    <p>
        <input type="submit" value="注册">
        <p style="color: red">{{ error_msg }}</p>
    </p>
</form>
</body>
</html>

三、使用form组件实现注册功能

views.py

先定义好一个RegForm类:

from django import forms

# 按照Django form组件的要求自己写一个类
class RegForm(forms.Form):
    name = forms.CharField(label="用户名")
    pwd = forms.CharField(label="密码")

再写一个视图函数:

# 使用form组件实现注册方式
def register2(request):
    form_obj = RegForm()
    if request.method == "POST":
        # 实例化form对象的时候,把post提交过来的数据直接传进去
        form_obj = RegForm(request.POST)
        # 调用form_obj校验数据的方法
        if form_obj.is_valid():
            return HttpResponse("注册成功")
    return render(request, "register2.html", {"form_obj": form_obj})

register2.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册2</title>
</head>
<body>
    <form action="/reg2/" method="post" novalidate autocomplete="off">
        {% csrf_token %}
        <div>
            <label for="{{ form_obj.name.id_for_label }}">{{ form_obj.name.label }}</label>
            {{ form_obj.name }} {{ form_obj.name.errors.0 }}
        </div>
        <div>
            <label for="{{ form_obj.pwd.id_for_label }}">{{ form_obj.pwd.label }}</label>
            {{ form_obj.pwd }} {{ form_obj.pwd.errors.0 }}
        </div>
        <div>
            <input type="submit" class="btn btn-success" value="注册">
        </div>
    </form>
</body>
</html>

看网页效果发现 也验证了form的功能:
• 前端页面是form类的对象生成的 -->生成HTML标签功能
• 当用户名和密码输入为空或输错之后 页面都会提示 -->用户提交校验功能
• 当用户输错之后 再次输入 上次的内容还保留在input框 -->保留上次输入内容

四、pycharm的专属测试环境

1.使用方法

1.导入要测试的py文件
2.生成一个对象

Django之form组件

Django之form组件

2.本地校验测试的一些参数

from_obj.is_valid()         //判断校验是否通过
from_obj.cleaned_data       //拿到当前符号校验的数据{'username': '111', 'password': '111'}
form_obj.errors             //拿到当前校验不通过的数据

少传参数Flalse,多传Trun。因为少传了拿不到校验的数据,多传了也不会使用。这是字典的形式

五、html渲染标签三种方式

forms组件只帮你渲染获取用户输入(输入 选择 下拉 文件)的标签 不渲染按钮和form表单标签
渲染出来的每一个input提示信息都是类中字段首字母大写

class MyRegForm(forms.Form):
    username = forms.CharField(max_length=8, min_length=3)  # 最长8位,最短3位
    password = forms.CharField(max_length=8, min_length=3)  # 最长8位,最短3位
    email = forms.EmailField()  # 邮箱验证
    
def reg(request):
    # 1 先生成一个空的类对象
    form_obj = MyRegForm()
    if request.method == 'POST':
        # 3 获取用户数据并交给forms组件校验  request.POST
        form_obj = MyRegForm(request.POST)
        # 4 获取校验结果
        if form_obj.is_valid():
            return HttpResponse('数据没问题')
        else:
            # 5 获取校验失败的字段和提示信息
            print(form_obj.errors)
    # 2 直接将该对象传给前端页面
    return render(request, 'reg.html', locals())

第一种方式 {{ form_obj.as_p }} (不推荐)

不推荐,封装程度高,扩展性低。一般测试本地用

<body>
<p>第一种渲染方式:多个p标签  本地测试方便 封装程度太高了 不便于扩展</p>
{{ form_obj.as_p }}
{#{{ form_obj.as_ul }}#}
{#{{ form_obj.as_table }}#}
</body>

Django之form组件

第二种方式 {{ form_obj.username }} (不推荐)

不推荐,扩展性较高 ,书写较为繁琐,每一个input框都需要自己手动写

<p>第二种渲染方式:  扩展性较高 书写较为繁琐</p>
<label for="{{ form_obj.username.id_for_label }}">{{ form_obj.username.label }}</label>
{{ form_obj.username }}
{{ form_obj.password.label }}{{ form_obj.password }}
{{ form_obj.email.label }}{{ form_obj.email }}

Django之form组件

第三种方式 for循环 (推荐)

推荐使用,for循环方式。也可以用ajax

{{ form.errors.0 }} # 这个是模板语法

<p>第三种渲染方式  推荐使用</p>
<form action="" method="post" novalidate>
    {% for form in form_obj %}
    <p>
        {{ form.label }}{{ form }}
        <span>{{ form.errors.0 }}</span>
    </p>
    {% endfor %}
    <input type="submit">
</form>

Django之form组件

Django之form组件

六、校验数据

*******数据校验一个前后端都得有 但是前端的校验弱不禁风 可有可无
而后端的校验则必须非常全面

forms组件默认所有的字段必须传值,少传不行,多传的数据不做任何的处理

如何取消浏览器自动帮我们校验的功能?

在form后加参数 no validate,不验证

form表单取消前端浏览器自动校验功能 
    <form action="" method="post" novalidate>

Django之form组件

常用校验参数

    max_length          //允许输入的最大长度
    min_length          //最小长度
  
    label               input的提示信息,name、password等
    error_messages      自定义报错的提示信息
        'max_length':"用户名最长8位",
        'min_length':"用户名最短3位",
        'required':"用户名不能为空"
    required            设置字段是否允许为空
    initial             设置默认值
    widget              控制type类型及属性   type   classs
    validator           正则校验及报错信息,并且支持多个

使用方式

CharField用户名类型校验

from django.forms import widgets   //不导入也可以,没提示

class MyRegForm(forms.Form):
    # 用户名最少3位最多8位
    username = forms.CharField(max_length=8,min_length=3,label='用户名',
                               error_messages={     //报错信息的提示
                                   'max_length':"用户名最长8位",
                                   'min_length':"用户名最短3位",
                                   'required':"用户名不能为空"
                               },required=False,initial='jeff',  // 为空和默认值
                               widget=forms.widgets.TextInput(attrs={'class':'form-control c1 c2'}),        //设置input的type属性为text,及class属性
                               )

Django之form组件

password校验

class LoginForm(forms.Form):
    ...
    pwd = forms.CharField(
        min_length=6,
        label="密码",
        widget=forms.widgets.PasswordInput(attrs={'class': 'c1'}, render_value=True)
    )

邮箱类型校验

class MyRegForm(forms.Form):
    # email字段必须填写符合邮箱格式的数据
    email = forms.EmailField(label='邮箱',error_messages={
        'required':'邮箱必填',
        'invalid':'邮箱格式不正确'
    })

Django之form组件

手机号类型校验

正则匹配

from django.core.validators import RegexValidator
class MyRegForm(forms.Form):
    # 手机号
    phone = forms.CharField(
        validators=[
            RegexValidator(r'^[0-9]+$', '请输入数字'),   
            RegexValidator(r'^159[0-9]+$', '数字必须以159开头')
        ]
    )

Django之form组件

性别校验

    gender = forms.ChoiceField(
        choices=((1, "男"), (2, "女"), (3, "保密")),
        label="性别",
        initial=3,
        widget=forms.widgets.RadioSelect()
    )

爱好单选 select校验

    hobby = forms.ChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
        label="爱好",
        initial=3,
        widget=forms.widgets.Select()   # 单选
    )

Django之form组件

爱好多选select 校验1

    hobby1 = forms.MultipleChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
        label="爱好",
        initial=[1, 3],
        widget=forms.widgets.SelectMultiple()
    )

Django之form组件

爱好多选chekbox校验2

    hobby2 = forms.MultipleChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
        label="爱好",
        initial=[1, 3],
        widget=forms.widgets.CheckboxSelectMultiple()
    )

Django之form组件

是否记住密码校验

    keep = forms.ChoiceField(
        label="是否记住密码",
        initial="checked",
        widget=forms.widgets.CheckboxInput()
    )

Django之form组件

七、钩子函数


# 如果你想同时操作多个字段的数据你就用全局钩子
# 如果你想操作单个字段的数据 你就用局部钩子
钩子勾回来处理完之后,还要还回去的

局部钩子

校验用户名中不能包含666

# 局部钩子
# 这里的self是自己类,MyRegForm
    def clean_username(self):
        username = self.cleaned_data.get('username')
        if '666' in username:
            self.add_error('username','光喊666是不行的')      //添加报错信息
        return username                                     //再把数据返回去

全局钩子

前面验证通过才走钩子函数验证。一层一层的验证

两次密码验证-----两个字段

class MyRegForm(forms.Form):
    # 密码
    password = forms.CharField(max_length=8,min_length=3,label='密码',
                               widget=forms.widgets.PasswordInput(attrs={'class':'form-control'})
                              )
    # 密码验证
    re_password = forms.CharField(max_length=8,min_length=3,label='确认密码',
                               widget=forms.widgets.PasswordInput(attrs={'class':'form-control'})
                                 )

    def clean(self):
        # 这里的self是自己类,MyRegForm
        # 校验密码和确认密码是否一致
        password = self.cleaned_data.get('password')
        re_password = self.cleaned_data.get('re_password')
        if not password == re_password:
            # 展示提示信息
            self.add_error('re_password','两次密码不一致')   // 添加报错信息
            return self.cleaned_data

Django之form组件