django—Form组件
django的Form组件主要实现的功能:
1、渲染html代码(不用手写相关前端表单代码)
2、校验数据
3、展示提示信息
Form组件的定义
以注册功能为例
from django import forms
class RegForm(forms.Form): user = forms.CharField() pwd = forms.CharField()
一个功能的form组件是一个类,这个类必须继承forms中的Form类(和模型类定义的形式有点类似);
这个类内部定义的成员变量就对应着前端页面的一个个input标签。
Form组件的基本使用
1、在视图函数中
def reg(request): form_obj = RegForm() return render(request, ‘reg.html‘, {‘form_obj‘: form_obj})
只需要将Form类实例化,传给对应的前端页面完成渲染,即可展示相应的表单内容
2、在模板文件中渲染
由于form组件只提供表单内部的元素,不包含表单以及按钮。所以在模板文件中需要手写相关代码。
<form action="" method="post"> {% csrf_token %} {{ form_obj.as_p }} <button>注册</button> </form>
以上代码在前端显示为
form_obj.as_p:将每个元素以p标签形式渲染出来(p标签内部有label和input)
3、标签渲染的方式
a、以不同形式,自动将所有元素一次性渲染出来,不利于后续扩展。
{{ form_obj.as_p }}
{{ form_obj.as_ul }}
{{ form_obj.as_table }}
b、根据from_obj内部的成员变量,手动生成想要的元素以及展示形式,扩展性高,代码冗余。
<p>{{ form_obj.user.label }}:{{ form_obj.user }}</p>
<p>{{ form_obj.pwd.label }}:{{ form_obj.pwd }}</p>
c、利用for循环生成元素,扩展性高,代码精简。
{% for form in form_obj %}
<p>{{ form.label }}:{{ form }}</p>
{% endfor %}
4、校验数据
后端要想使用Form组件进行数据的校验,首先需要关闭前端的校验(直接将数据给后端)
只需要在from标签内加上novalidate属性即可
后端校验数据:
def reg(request): form_obj = RegForm() # 空的Form对象 if request.method == ‘POST‘: form_obj = RegForm(request.POST) # 包含用户提交的数据的From对象 if form_obj.is_valid(): # 对数据进行校验 return HttpResponse(‘ok‘) # 如果校验不成功,那么render返回的form_obj中就包含了对应字段的错误信息,可以渲染在前端 return render(request, ‘reg.html‘, {‘form_obj‘: form_obj})
前端可以通过{{ form_obj.errors }}打印出所有的错误,也可以根据不同字段来打印错误信息{{ form_obj.user.errors }}
如果某个字段有多个错误还可以通过下标的方式选择打印错误信息{{ form_obj.user.errors.0 }},否则是以列表的形式展示数据
form组件会在数据不合法的情况下,保存上次的数据,让用户基于上次的数据进行修改。
Form常用的字段和参数
1、常用字段
Form组件可用的字段有:
__all__ = ( ‘Field‘, ‘CharField‘, ‘IntegerField‘, ‘DateField‘, ‘TimeField‘, ‘DateTimeField‘, ‘DurationField‘, ‘RegexField‘, ‘EmailField‘, ‘FileField‘, ‘ImageField‘, ‘URLField‘, ‘BooleanField‘, ‘NullBooleanField‘, ‘ChoiceField‘, ‘MultipleChoiceField‘, ‘ComboField‘, ‘MultiValueField‘, ‘FloatField‘, ‘DecimalField‘, ‘SplitDateTimeField‘, ‘GenericIPAddressField‘, ‘FilePathField‘, ‘SlugField‘, ‘TypedChoiceField‘, ‘TypedMultipleChoiceField‘, ‘UUIDField‘, )
CharField——文本输入框
EmailField——邮箱文本输入框(输入的字段必须符合邮箱的格式)
ChoiceField——单选框 默认是select
MultipleChoiceField——多选框 默认是select
2、字段参数
initial——设置默认值
error_messages——重写错误信息(默认错误信息是固定格式且是英文的)
error_messages={ "required": "不能为空", "invalid": "格式错误", "min_length": "用户名最短8位" }
label——设置字段名,前端默认展示的字段名是首字母大写的成员变量名
choices——设置选择框的选项,每个选项都以元组形式存储(存储在数据库的值,前端页面展示的值)
required——设置字段是必填项
disabled——设置input是否禁用
validators——设置字段的校验器,对应值是一个列表,列表内存放函数对象,即相关校验函数。
widget——插件,修改input的类型
widget=forms.PasswordInput(attrs={‘class‘:‘form-control c1 c2‘})
修改input类型的同时还能够设置属性值
可选的类型如下:
__all__ = ( ‘Media‘, ‘MediaDefiningClass‘, ‘Widget‘, ‘TextInput‘, ‘NumberInput‘, ‘EmailInput‘, ‘URLInput‘, ‘PasswordInput‘, ‘HiddenInput‘, ‘MultipleHiddenInput‘, ‘FileInput‘, ‘ClearableFileInput‘, ‘Textarea‘, ‘DateInput‘, ‘DateTimeInput‘, ‘TimeInput‘, ‘CheckboxInput‘, ‘Select‘, ‘NullBooleanSelect‘, ‘SelectMultiple‘, ‘RadioSelect‘, ‘CheckboxSelectMultiple‘, ‘MultiWidget‘, ‘SplitDateTimeWidget‘, ‘SplitHiddenDateTimeWidget‘, ‘SelectDateWidget‘, )
通过修改CharField的类型,可以实现其他字段的效果。
补充:
前端展示选择框数据的时候,往往这些数据都是写死的。
可以将选择框数据单独存放在表中,然后将该表的查询结果作为展示数据,这样前端展示选择框数据时就可以实现动态展示。
首先需要导入 from django.forms import models as form_model
hobby = form_model.ModelMultipleChoiceField( queryset=models.Hobby.objects.all(), widgets=forms.CheckboxSelectMultiple)
校验方法
1、设置校验器
定义校验函数
from django.core.exceptions import ValidationError def check_name(value): if ‘1‘ in value: raise ValidationError(‘该用户名不符合要求‘)
在相应字段加上validators参数
user = forms.CharField(label=‘用户名‘, validators=[check_name])
校验函数内,出现不符合校验标准的情况必须抛出ValidationError异常,异常信息作为校验错误的提示信息
2、定义钩子函数
钩子函数需要定义在Form类当中
a、局部钩子
函数的命名为clean_字段名
class RegForm(forms.Form): user = forms.CharField(label=‘用户名‘) pwd = forms.CharField(label=‘密码‘, widget=forms.PasswordInput()) def clean_user(self): value = self.cleaned_data.get(‘user‘) if ‘1‘ in value: # 不符合校验规则 raise ValidationError(‘该用户名不符合要求‘) # 符合校验规则 return value
cleaned_data是经过is_valid()校验过,没有问题的数据字典
使用is_valid()方法前,没有cleaned_data字典,获取时会报错
只有在is_valid()方法之后,才生成了cleaned_data字典
b、全局钩子
全局钩子命名为clean,针对所有字段
def clean(self): username = self.cleaned_data.get(‘user‘) pwd = self.cleaned_data.get(‘pwd‘) if ‘1‘ in username: # 不符合校验规则 raise ValidationError(‘该用户名不符合要求‘) if ‘1‘ in pwd: raise ValidationError(‘密码包含禁用词‘) # 符合校验规则 返回所有字段的值 return self.cleaned_data
此时,抛出的错误信息存放在全局{{ form_obj.errors }},不能通过字段名的错误信息获取到
要想将错误信息存放在某个字段当中,可以通过以下方法:
self.add_error(字段名,错误信息)
self.add_error(‘pwd‘, ‘错误‘)
注意:
钩子函数中出现不符合校验规则的情况,必须要抛出异常。
即便已经将某个错误信息存放到指定字段中,也需要抛出异常(固定搭配)