form组件

form组件能做的事:

1 渲染html代码

2 校验数据
3 展示提示信息

校验数据

from app01 import models
from app01 import views
# 1 将待校验的数据组织成字典的形式传入即可					(传错)
form_obj = views.MyForm({'username':'jason','password':'123','email':'123'}) 
# 2 判断数据是否合法, 注意:该方法只有在数据全部合法的情况下才会返回true
form_obj.is_valid()
False
# 3 查看所有校验通过的数据
form_obj.cleaned_data
{'username': 'jason', 'password': '123'}
# 4 查看所有不符合校验规则的参数以及不符合的原因
form_obj.errors
{'email': ['Enter a valid email address.']}
# 5 校验数据只校验类中出现的字段,多传不影响,多传的字段直接忽略。 (多传)
form_obj = views.MyForm({'username':'jason','password':'123','email':'123@q.com','hobby':'study'})
form_obj.is_valid()
True
# 6  校验数据,默认情况下,类里面所有的字段都必须传值		(少传)
form_obj = views.MyForm({'username':'jason','password':'123'})
form_obj.is_valid()
False

form_obj.errors
{'email': ['This field is required.']}
校验数据的时候,默认情况下,数据可以多传但是绝不可能少传。
form_obj = views.MyForm({'username':'jason','email':'123'}) #创建froms对象
form_obj.cleaned_data		# 查看校验通过的数据
form_obj.errors 		# 查看错误的数据
form_obj.is_valid() 		# 判断数据是否合法。

渲染标签


# form组件渲染html标签
def index(request):
    # 1 先产生一个空对象
    form_obj = MyForm()
    # 2 直接将空对象传递给html页面
    return render(request, 'index.html',locals())

# 前提是要先在后端生成一个空对象,然后前端利用空对象做操作
    <p>第一种渲染方式:代码书写极少,封装程度太高,不便于后续的扩展,一般情况下只在本地测试使用。</p>
    {{ form_obj.as_p }}
    {{ form_obj.as_ul }}
    {{ form_obj.as_table }}

    <p>第二种渲染方式:可扩展性很强 但是需要书写的代码太多 一般不用</p>
    <p>{{ form_obj.username.label }}:{{ form_obj.username }}</p>
    <p>{{ form_obj.password.label }}:{{ form_obj.password }}</p>
    <p>{{ form_obj.email.label }}:{{ form_obj.email }}</p>
        
    <p>第三种渲染方式(推荐使用):代码书写简单,并且扩展性也高</p>
    {% for form in form_obj %}
        <p>{{ form.label }}:{{ form }}</p>
    {% endfor %}  '遍历对象内的属性,使用for循环依次渲染'

"""
label 属性默认展示的是类中定义的字段首字母大写的形式
也可以自己修改,直接给字段对象加label属性即可。
username = forms.CharField(min_length=3,max_length=8,label='用户名')
"""

展示提示信息(可自定义)

如何让浏览器不自动校验?  在form表的属性中加 novalidate(无校验)
<form action="" method="post" novalidate>


 {% for form in form_obj %}
        <p>
            {{ form.label }}:{{ form }}
            <span style="color: red">{{ form.errors.0 }}</span>
        </p>
    {% endfor %}
    <input type="submit" class="btn btn-info">
form组件渲染html标签
def index(request):
    # 1 先产生一个空对象
    form_obj = MyForm() # 这里
    if request.method == 'POST':
        pass
        # 获取用户数据并校验
    """
    1 获取数据繁琐
    2 校验数据需要构造成字段格式传入才行
    ps:但是request.POST可以看成是一个字典
    """
    # 3 校验数据
    *form_obj = MyForm(request.POST) # 这里

    # 4 判断数据是否合法
    if form_obj.is_valid():
        # 5 如果合法,操作数据库存储数据
        return HttpResponse('ok')
    # 5 不合法有错误
    #     # 如何将错误信息展示到前端。
    # 2 直接将空对象传递给html页面
    return render(request, 'index.html', locals())

"""
1 必备条件 get请求和post传给html页面对象变量名必须一样(这里)
2 froms组件当你的数据不合法的情况下, 会保存上次的数据,让你基于之前的结果进行修改,更加的人性化
"""  
针对错误的提示信息,可以自己定制
class MyForm(forms.Form):
    # username 字符串类型最小3位,最大8位
    username = forms.CharField(min_length=3, max_length=8, label='用户名',
                               error_messages={
                                   'min_length':'用户名最少3位',
                                   'max_length':'用户名最多8位',
                                   'required':'用户名不能位空'
                               })
    # password 字符串类型最小3位,最大8位
    password = forms.CharField(min_length=3, max_length=8, label='密码',
                               error_messages={
                                   'min_length': '密码最少3位',
                                   'max_length': '密码最多8位',
                                   'required': '密码不能位空'
                               }
                               )
    # email字段必须符合邮箱格式 xxxx@xxx.com
    email = forms.EmailField(label='邮箱',
                             error_messages={
                                 'invalid':'邮箱格式不正确',
                                 'required': '邮箱不能位空'
                             }
                             )

钩子函数

钩子函数在forms组件中,就类似于第二道关卡,除了forms组件自带的校验规则,还可以自定义校验规则。


局部钩子和全局钩子

局部钩子:

        用在给单个字段增加校验规则时候,例如:用户名中不能含有某个字母

全局钩子:

        用在需要给多个字段增加校验规则的时候,例如:校验密码和再次输入密码,两个值是否相同

from django import forms
from app01 import models


class MyRegForm(forms.Form):     '钩子函数直接写在forms类中即可'
    username = forms.CharField(label='用户名', min_length=3, max_length=8,
                               error_messages={
                                   'required': '用户名不能为空',
                                   'min_length': '用户名最少三位',
                                   'max_length': '用户名最大八位',
                               },
                               # 还需要让标签有bootstrap样式
                               widget=forms.widgets.TextInput(attrs={'class': 'form-control'})
                               )
    password = forms.CharField(label='密码', min_length=3, max_length=8,
                               error_messages={
                                   'required': '密码不能为空',
                                   'min_length': '密码最少三位',
                                   'max_length': '密码最大八位',
                               },
                               # 还需要让标签有bootstrap样式
                               widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'})
                               )
    confirm_password = forms.CharField(label='确认密码', min_length=3, max_length=8,
                                       error_messages={
                                           'required': '确认密码不能为空',
                                           'min_length': '确认密码最少三位',
                                           'max_length': '确认密码最大八位',
                                       },
                                       # 还需要让标签有bootstrap样式
                                       widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'})
                                       )
    email = forms.EmailField(label='邮箱',
                             error_messages={
                                 'required': '邮箱不能为空',
                                 'invalid': '邮箱格式不正确',
                             },
                             widget=forms.widgets.EmailInput(attrs={'class': 'form-control'})
                             )



 # 1 局部钩子
    def clean_username(self):  # clean_username     // clean_  有几个字段就出几个
        # 获取用户名
        username = self.cleaned_data.get('username')
        if '666' in username:
            # 提示前端展示错误信息
            self.add_error('username', '666不允许存在')
        # 将钩子函数钩取出来的数据再放回去
        return username 


    # 2全局钩子
    def clean(self):
        password = self.cleaned_data.get('password')
        confirm_password = self.cleaned_data.get('confirm_password')
        if not confirm_password == password:
            self.add_error('confirm_password', '两次密码不一致')
        # 将钩子函数钩出来的数据全部返回
        return self.cleaned_data


#  钩子函数,在类里面书写方法即可

forms组件其他参数及补充

lable  字段名 给字段起名字
error_messages  自定义报错信息
initial		 默认值
required=False  控制字段是否必填
max_length 	最大位数
min_length	最小位数
widget		控制标签样式,类,属性
validators 让数据校验支持正则


针对不同类型的input 如何修改
text
password
date
radio
checkbox



"""
widget=forms.widgets.TextInput(attrs={'class':'form-control','username':'jason'})
# 写成字典格式,可以传单个属性,也可以自定义属性




widget=forms.widgets.PasswordInput(attrs={'class':'form-control c1 c2'})
# 多个属性值的话直接空格隔开即可,
# PasswordInput 控制type 类型的
# attrs={'class':'form-control c1 c2'} 控制属性的


RegexValidator验证器(使数据校验支持)



from django.forms import Form
from django.forms import widgets
from django.forms import fields
from django.core.validators import RegexValidator
 
class MyForm(Form):
    user = fields.CharField(
        validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')],
    )

其他类型渲染

'写在forms类中即可 然后前端通过for循环,会一起渲染到前端页面'
    # radio
    gender = forms.fields.ChoiceField(
        choices=((1, "男"), (2, "女"), (3, "保密")),
        label="性别",
        initial=3,
        widget=forms.widgets.RadioSelect()
    )
    
    # select
    hobby = forms.ChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
        label="爱好",
        initial=1,  # 默认值
        widget=forms.widgets.Select()
    )
    
    # 多选select
    hobby2 = forms.MultipleChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
        label="爱好",
        initial=[1, 3],
        widget=forms.widgets.SelectMultiple(attrs={'class': 'form-control'})
    )
    
    # 单选checkbox
    keep = forms.ChoiceField(
        label="是否记住密码",
        initial="checked",
        widget=forms.widgets.CheckboxInput(),
    )
    # 多选 checkbox
    hobby3 = forms.MultipleChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
        label="爱好",
        initial=[1, 3],
        widget=forms.widgets.CheckboxSelectMultiple()
    )

forms数据校验总结

lable  字段名 给字段起名字
error_messages  自定义报错信息
initial		 默认值
required=False  控制字段是否必填
max_length 	最大位数
min_length	最小位数
widget		控制标签样式,类,属性
validators 让数据校验支持正则

"""
针对字段的校验有很多种
1 最简单的	min_length
2 正则	validators
3 钩子函数

前端的校验可有可无,但是后端的校验一点都不能含糊

form表单如何取消浏览器自动校验功能
在form表的属性中加 novalidate(无校验)
<form action="" method="post" novalidate></from>

forms组件源码

"""
切入点:
	form_obj.is_valid()
"""
···············································
def is_valid(self): 
        """
        Returns True if the form has no errors. Otherwise, False. If errors are
        being ignored, returns False.
        """
    return self.is_bound and not self.errors    
# 如果is_valid要返回true的话 self.is_bound 要为true , self.errors 要为false 


self.is_bound = data is not None or files is not None  # 只要传值了is_bound肯定为true

········································
 @property
    def errors(self):
        "Returns an ErrorDict for the data provided for the form"
        if self._errors is None:
            self.full_clean()
        return self._errors
················································ 
    def full_clean(self):  
        """
        Cleans all of self.data and populates self._errors and
        self.cleaned_data.
        """
        self._errors = ErrorDict()
        if not self.is_bound:  # Stop further processing.
            return
        self.cleaned_data = {}
        # If the form is permitted to be empty, and none of the form data has
        # changed from the initial data, short circuit any validation.
        if self.empty_permitted and not self.has_changed():
            return

        self._clean_fields()	 # 校验字段 + 自动调用局部钩子	
        self._clean_form()		#  全局钩子需要一个返回值,cleaned_data
        self._post_clean()	
        ' forms组件的主要方法都来自上面三个方法'
····························································

 def _clean_fields(self):
        for name, field in self.fields.items(): # 循环获取字段名和字段对象
          
        
 		value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))  # 获取字段对应的用户数据

     self.cleaned_data[name] = value  # 将合法的字段添加到cleaned_data
     if hasattr(self, 'clean_%s' % name):   # 利用反射获取局部钩子函数
        value = getattr(self, 'clean_%s' % name)()	#局部钩子需要有返回值 
        self.cleaned_data[name] = value 

try:
    xxxxxx
except ValidationError as e:
    self.add_error(name, e)
    
    
总结: self._clean_fields()	 # 校验字段 + 自动调用局部钩子	
      self._clean_form()	# 全局钩子需要一个返回值,cleaned_data
    主要用了这两个方法 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值