Django框架(十六)—— forms组件局部钩子全局钩子

Posted linagcheng

tags:

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

forms组件、局部钩子、全局钩子

一、什么是forms组件

forms组件就是一个类,可以检测前端传来的数据,是否合法。
例如,前端传来的邮箱数据,判断邮件格式对不对,用户名中不能以什么开头,等等

二、forms组件的使用

1、使用语法

from django.shortcuts import render, HttpResponse
from django import forms

# 1.先写一个类,继承Form
class MyForm(forms.Form):
    # 定义一个属性,可以用来校验字符串类型
    # 限制最大长度是8,最小长度是3
    name=forms.CharField(max_length=8,min_length=3)
    pwd=forms.CharField(max_length=8,min_length=3,required=True)
    # 校验是否是邮箱格式
    email=forms.EmailField()

# 2.实例化产生对象,传入要校验的数据(可以传字典字典,也可以不传)
myform=MyForm(request.POST)

# 3.校验,is_valid如果是true表示校验成功(满足myform里的条件),反之,校验失败
if myform.is_valid():
    # 校验通过的数据
    print(myform.cleaned_data)
    return HttpResponse(‘校验成功‘)
else:
    print(myform.cleaned_data)
    #校验失败的信息,myform.errors  可以当成一个字典,它是所有错误信息{name:[列表,]}
    # 每个字段.errors 是一个列表,表示每个字段的错误信息
    print(myform.errors)
    return HttpResponse(‘校验失败‘)

2、组件的参数

max_length    # 代表该字段最长为多少
min_length    # 代表该字段最短为多少
error_messages   # 这是设置错误信息的属性
required   # 默认值为True,意思是你传来的字段必须有它,没有的话校验失败
widget=widgets.TextInput()  # 你在模板渲染的时候,就会渲染成Input框,type为text
lable   # lable=‘用户名‘

# 例子
 pwd = forms.CharField(max_length=8, min_length=3, required=True, label=‘密码‘,
                          error_messages={‘max_length‘: ‘最长是8‘, ‘min_length‘: ‘最短是3‘, ‘required‘: ‘这个必须填‘},

3、注意点

  • MyForm实例化时,传入必须是字典,或者不传
  • errors 调用这个方法,返回值是对象,你可以通过get取值

三、渲染模板

# form组件可以在视图函数中使用,也可以在模板中使用
# 视图层:
def index(request):
    myform = Myform()
    return render(request,‘index.html‘,local())
# 模板层
# 1.渲染方式一:
    <form action=‘‘ method=‘post‘>
        用户名:{{myform:name}} <br>
        <input type=‘submit‘ value = ‘提交‘></input>
    </form>
    # 这里的{{myform:name}} 和你写input框是一样的效果,就是属性比input框多一点

# 2.渲染方式二(推荐使用):
    <form action=‘‘ method=‘post‘>
        {% for foo in myform%}
            {{ foo.lable }} : {{ foo }}  <br>
        <input type=‘submit‘ value = ‘提交‘></input>
    </form>
    # 页面显示都是一样的,foo.lable不是用户名,是name,但是可以在创建Myform类时,在CharFiel中添加lable=‘用户名‘,这样就行了。

# 3.渲染方式三:
    <form action=‘‘ method=‘post‘>
         {{ myform.as_p }}
        <input type=‘submit‘ value = ‘提交‘></input>
    </form>

四、渲染错误信息

<form action=‘‘ method=‘post‘>
    {% for foo in myform%}
        {{ foo.lable }} : {{ foo }} <span>{{foo.errors.0}}</span><br>
    <input type=‘submit‘ value = ‘提交‘></input>
</form>

五、局部钩子

1、什么是局部钩子

定义一个函数,名字叫:clean_字段名字,内部,取出该字段,进行校验,如果通过,将该字段返回,如果失败,抛异常(ValidationError)

2、定义局部钩子

def clean_name(self):
    # self:当前form对象
    name = self.cleaned_data.get(‘name‘)
    if name.startswith(‘sb‘):
        # 失败,抛异常
        raise ValidationError(‘不能以sb开头‘)
    # 正常,把name返回
    return name

六、全局钩子

1、什么是全局钩子

在写注册用户的时候,有输入密码,确认密码,可以进行布局钩子处理,处理完毕是不是在进行判断,判断他们是否相等,相等的话,就存到数据库中,不相等就抛个异常。

2、定义全局钩子

# 重写clean方法
def clean(self):
    # 程序能走到该函数,前面校验已经通过了,所以可以从cleaned_data中取出密码和确认密码        
    pwd=self.cleaned_data.get(‘pwd‘)
    re_pwd=self.cleaned_data.get(‘re_pwd‘)
    # 进行自己的校验
    if pwd==re_pwd: 
        # 通过,直接返回cleaned_data
        return self.cleaned_data
    else:
        # 失败,抛异常(ValidationError)
        raise ValidationError(‘两次密码不一致‘)
        

注意点:

  • 局部钩子抛出的异常会添加到该字段中的错误信息中,也就是myform.errors.get(字段名)中
  • 全局钩子抛出的异常会添加到_all_中,myform.errors.get(‘_all_‘)中可以取到
  • 如果程序走到了局部钩子这一步,说明传的字典里的数据符合要求,此时就可以从clean_data中取数据,因为此时clean_data中的数据全符合要求,而且clean_data是一个字典
  • 局部钩子,全局钩子所抛出异常的类型为ValidationError,以下导入
from django.core.exceptions import ValidationError

七、完整的forms组件校验

1、视图层

from django.shortcuts import render, HttpResponse, redirect

# forms组件数据校验的功能
# 第一步:先要继承Form
from django import forms
from django.forms import widgets
from django.core.exceptions import ValidationError


# 写一个类
class MyForm(forms.Form):
    # 定义一个属性,可以用来校验字符串类型
    # 限制最大长度是8,最小长度是3
    name = forms.CharField(max_length=8, min_length=3, label=‘用户名‘,
                           error_messages={‘max_length‘: ‘最长是8‘, ‘min_length‘: ‘最短是3‘, ‘required‘: ‘这个必须填‘},
                           widget=widgets.TextInput(attrs={‘class‘: ‘form-control‘}))
    pwd = forms.CharField(max_length=8, min_length=3, required=True, label=‘密码‘,
                          error_messages={‘max_length‘: ‘最长是8‘, ‘min_length‘: ‘最短是3‘, ‘required‘: ‘这个必须填‘},
                          widget=widgets.PasswordInput())
    re_pwd = forms.CharField(max_length=8, min_length=3, required=True, label=‘确认密码‘,
                             error_messages={‘max_length‘: ‘最长是8‘, ‘min_length‘: ‘最短是3‘, ‘required‘: ‘这个必须填‘},
                             widget=widgets.PasswordInput())
    # 校验是否是邮箱格式
    email = forms.EmailField(label=‘邮箱‘, error_messages={‘required‘: ‘这个必须填‘, ‘invalid‘: ‘不符合邮箱格式‘})

    # aa = forms.CharField(label=‘选择‘, error_messages={‘required‘: ‘这个必须填‘, ‘invalid‘: ‘不符合邮箱格式‘},widget=widgets.CheckboxInput())
    def clean_name(self):
        # self:当前form对象
        name = self.cleaned_data.get(‘name‘)
        if name.startswith(‘sb‘):
            # 失败,抛异常
            raise ValidationError(‘不能以傻逼开头‘)
        # 正常,把name返回
        return name

    def clean(self):
        pwd = self.cleaned_data.get(‘pwd‘)
        re_pwd = self.cleaned_data.get(‘re_pwd‘)
        if pwd == re_pwd:
            return self.cleaned_data
        else:
            raise ValidationError(‘两次密码不一致‘)


def index_form(request):
    # 生成对象时(实例化),需要传入要校验的数据(字典)
    if request.method == ‘GET‘:
        myform = MyForm()
        return render(request,‘indxe2.html‘,locals())
    elif request.method == ‘POST‘:
        myform = MyForm(request.POST)
        if myform.is_valid():
            print(myform.cleaned_data)

            # models.User.objects.create(name=‘lqz‘,pwd=‘123‘,re_pwd=‘123)
            myform.cleaned_data.pop(‘re_pwd‘)
            models.User.objects.create(**myform.cleaned_data)
            return redirect(‘http://www.baidu.com‘)
        else:
            all_error = myform.errors.get(‘__all__‘)
            if all_error:
                all_error = all_error[0]
            # print(myform.errors.as_data)

    return render(request, ‘indxe3.html‘, locals())

2、模板层

<form action="" method="post" novalidate>
    {% for foo in myform %}
        <p>{{ foo.label }}:{{ foo }} <span>{{ foo.errors.0 }}</span></p>
    {% endfor %}

    <input type="submit" value="提交"><span>{{ all_error }}</span>
</form>

以上是关于Django框架(十六)—— forms组件局部钩子全局钩子的主要内容,如果未能解决你的问题,请参考以下文章

Django---FORM组件.FORM组件的字段,FORM组件校验流程,FORM组件的全局和局部钩子,FORM和Model的组合

Django框架11

Django框架11

Django Form 组件

Django学习——forms组件源码分析

Django 框架篇: Django中的Form 组件