加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

Form组件

发布时间:2020-12-15 01:58:05 所属栏目:Java 来源:网络整理
导读:手动实现登录校验的功能 前端代码 form action= "" method= " post " { % csrf_token % } pusername:input type= " text " name= " username " value= " {{ username }} " span{{ back_dic.username }}/span/p ppassword:input type= " text " name= " passw

手动实现登录校验的功能

前端代码

<form action="" method="post">
    {% csrf_token %}
    <p>username:<input type="text" name="username" value="{{ username }}"><span>{{ back_dic.username }}</span></p>
    <p>password:<input type="text" name="password" value="{{ password }}"><span>{{ back_dic.password }}</span></p>
    <p><input type="submit"></p>
</form>
前端

后端代码

def register(request):
    back_dic = {
        "username":"","password":""
    }
    username = ""
    password = ""
    if request.method == POST:
        username = request.POST.get("username")
        password = request.POST.get("password")
        if "666"in username:        # 不符合,就把提示信息加入到字典中,在页面中相应的地方渲染
            back_dic["username"] = "喊6剁手"
        if len(password) < 3:
            back_dic["password"] = "密码太短"

    return render(request,"register.html",locals())
# 除了大字典传参渲染页面之外, locals()也可以传参渲染,并且locals()会把定义的变量全部传过去
后端

上述代码我们一共实现三个功能

  1. 渲染页面

  2. 对数据进行校验

  3. 展示提示信息

form组件实现的功能

form组件主要也是帮我们实现上面三个功能

1. 对数据进行校验

数据校验分为前端校验和后端校验两种,前端校验可以不做,后端校验必须做

因为前端很脆弱,别人可容易就会越过你的校验,如果我们后端不做校验

就会很危险,后端校验如下

# 使用form组件的第一步就是需要我们自己写一个类去继承forms.Form
from django import forms
class MyForm(forms.Form):
    username = forms.CharField(max_length=6,label="用户名")
                            # max_length表示限制条件,  label表示文本信息
    password = forms.CharField(max_length=6,min_length=3,label="密码",error_messages={"min_length":"密码太短"})

def register(request):
    # 生成一个form对象
    form_obj = MyForm()

    if request.method == POST:
        # 前端传过来数据之后
        # 1. 给form组件传参,字典的形式
        form_obj = MyForm(request.POST)
        # 2.判断数据是否全部合法 is_valid()
        print(form_obj.is_valid())  # is_valid() 方法会校验你传入的数据是否符合定义的限制
                                    # 只要有一个不符合就会返回False
        # 3. 查看所有校验通过的数据cleaned_data
        print(form_obj.cleaned_data)
        # 4. 查看所有没通过的数据及其报错信息errors
        print(form_obj.errors)
    return render(request,"register.html",locals())

2. 渲染页面

渲染页面主要有三种方式

第一种渲染标签方式(本地)

{{ form_obj.as_p }}

直接通过forms对象点as_p 就可以生成所有被p包裹的标签,

如果点as_ul,就会生成被li包裹的标签,并且在展示时,默认会把label标签的首字母大写

但是这种方法的封装程度太高,不方便我们后期添加样式,所以基本上作本地测试用

第二种渲染标签方式(可扩展性高)

<p>{{ form_obj.username.label }}{{ form_obj.username }}</p>
<p>{{ form_obj.password.label }}{{ form_obj.password }}</p>

我们自己定义标签,通过forms对象点出单独的标签,这种方式的扩展性高

但是如果我们forms对象的字段比较多的话,一个一个点比较麻烦

第三种渲染标签的方式(常用)

{% for foo in form_obj %}
    {{ foo.label }}{{ foo }}
{% endfor %}

我们可以循环forms对象,得到是每一个字段对应的标签,这样我们就可以

通过点语法得到我们想要的标签(扩展性高且不用写太多代码)

3. 展示错误信息

当我们渲染完标签之后,我们会发现当我们输入错误信息的时候,浏览器端

会提示我们报错信息,如下

这种提示错误信息的方式其实是forms组件在前端做了判断,并展示出报错信息

前面我们也提到过,既然后端进行了数据校验,那么我们可不可以自定义提示信息呢

如果我们想展示后端错误信息,那首先需要让前端停止校验

<form action="" method="post" novalidate>

novalidate的意思就是让前端停止校验

首选我们需要在每个字段中添加错误条件及其对应的提示 error_messages

password = forms.CharField(max_length=6,label="密码",error_messages={
                               "min_length":"密码太短","max_length":"密码太长"
                                           })

然后我们在前端,可以通过.errors拿到报错信息的一个列表,索引0取出信息

{% for foo in form_obj %}
    <p>{{ foo.label }}{{ foo }} {{ foo.errors }}</p>
{% endfor %}

这样就可以展示出我们自己的提示信息了

还有一点之前忘了补充:

那就是如果我们不用forms组件去提示错误信息,那也会把用户之前输入的

信息全部刷新掉,这种体验是非常差的,而我们的forms组件则会保留之前的信息

form组件的hook函数(钩子函数)

上面展示的错误提示都是一些系统里面自带的校验规则,例如最大、最小长度

那我们想自己定义一些规则,例如用户名不能包含666,这就需要用到钩子函数

钩子函数分为两种,局部钩子与全局钩子

局部钩子

局部钩子只能对单个字段进行二次校验

def clean_username(self):   # 局部钩子通过clean_字段名 定义, 只要在上面出现过的字段,在这都会有提示
    username = self.cleaned_data.get("username")  # 然后我们取值需要从校验成功这里面取值
    if "666" in username: # 进行判断,错误就通过add_error添加到错误信息中
        self.add_error("username","不能包含666") # add_error("字段名","错误信息")
    return username # 为了健壮性, 就把username返出去

全局钩子

全局钩子可以对多个字段联合起来校验

def clean(self): # 全局钩子直接通过clean来定义
    password = self.cleaned_data.get("password")
    confirm_password = self.cleaned_data.get("confirm_password")
    if password != confirm_password:
        self.add_error("confirm_password","两次密码不一致")
    return self.cleaned_data

不管是全局钩子,还是局部钩子,都只有在通过了第一次校验之后,才会进入钩子函数

forms组件类中一些其他字段及参数

Field
    required=True,是否允许为空
    widget=None,HTML插件
    label=None,用于生成Label标签或显示内容
    initial=None,初始值
    help_text=‘‘,帮助信息(在标签旁边显示)
    error_messages=None,错误信息 {required: 不能为空,invalid: 格式错误}
    validators=[],自定义验证规则
    localize=False,是否支持本地化
    disabled=False,是否可以编辑
    label_suffix=None            Label内容后缀
 
 
CharField(Field)
    max_length=None,最大长度
    min_length=None,最小长度
    strip=True                   是否移除用户输入空白
 
IntegerField(Field)
    max_value=None,最大值
    min_value=None,最小值
 
FloatField(IntegerField)
    ...
 
DecimalField(IntegerField)
    max_value=None,最小值
    max_digits=None,总长度
    decimal_places=None,小数位长度
 
BaseTemporalField(Field)
    input_formats=None          时间格式化   
 
DateField(BaseTemporalField)    格式:2015-09-01
TimeField(BaseTemporalField)    格式:11:12
DateTimeField(BaseTemporalField)格式:2015-09-01 11:12
 
DurationField(Field)            时间间隔:%d %H:%M:%S.%f
    ...
 
RegexField(CharField)
    regex,自定制正则表达式
    max_length=None,最小长度
    error_message=None,忽略,错误信息使用 error_messages={invalid: ...}
 
EmailField(CharField)      
    ...
 
FileField(Field)
    allow_empty_file=False     是否允许空文件
 
ImageField(FileField)      
    ...
    注:需要PIL模块,pip3 install Pillow
    以上两个字典使用时,需要注意两点:
        - form表单中 enctype="multipart/form-data"
        - view函数中 obj = MyForm(request.POST,request.FILES)
 
URLField(Field)
    ...
 
 
BooleanField(Field)  
    ...
 
NullBooleanField(BooleanField)
    ...
 
ChoiceField(Field)
    ...
    choices=(),选项,如:choices = ((0,上海),(1,北京),)
    required=True,是否必填
    widget=None,插件,默认select插件
    label=None,Label内容
    initial=None,帮助提示
 
 
ModelChoiceField(ChoiceField)
    ...                        django.forms.models.ModelChoiceField
    queryset,# 查询数据库中的数据
    empty_label="---------",# 默认空显示内容
    to_field_name=None,# HTML中value的值对应的字段
    limit_choices_to=None      # ModelForm中对queryset二次筛选
     
ModelMultipleChoiceField(ModelChoiceField)
    ...                        django.forms.models.ModelMultipleChoiceField
 
 
     
TypedChoiceField(ChoiceField)
    coerce = lambda val: val   对选中的值进行一次转换
    empty_value= ‘‘            空值的默认值
 
MultipleChoiceField(ChoiceField)
    ...
 
TypedMultipleChoiceField(MultipleChoiceField)
    coerce = lambda val: val   对选中的每一个值进行一次转换
    empty_value= ‘‘            空值的默认值
 
ComboField(Field)
    fields=()                  使用多个验证,如下:即验证最大长度20,又验证邮箱格式
                               fields.ComboField(fields=[fields.CharField(max_length=20),fields.EmailField(),])
 
MultiValueField(Field)
    PS: 抽象类,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用
 
SplitDateTimeField(MultiValueField)
    input_date_formats=None,格式列表:[%Y--%m--%d,%m%d/%Y,%m/%d/%y]
    input_time_formats=None    格式列表:[%H:%M:%S,%H:%M:%S.%f,%H:%M]
 
FilePathField(ChoiceField)     文件选项,目录下文件显示在页面中
    path,文件夹路径
    match=None,正则匹配
    recursive=False,递归下面的文件夹
    allow_files=True,允许文件
    allow_folders=False,允许文件夹
    required=True,widget=None,label=None,initial=None,help_text=‘‘
 
GenericIPAddressField
    protocol=both,both,ipv4,ipv6支持的IP格式
    unpack_ipv4=False          解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1, PS:protocol必须为both才能启用
 
SlugField(CharField)           数字,字母,下划线,减号(连字符)
    ...
 
UUIDField(CharField)           uuid类型


Django Form内置字段
字段及参数

具体内容及使用方法

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读