Chapter VI, forms component

Chapter VI, forms component

First, the registration function handwriting

Claim

1.注册功能
            用户输入的用户名中 不能包含西游记
                如果包含了 就提示用户 输入的内容不符合社会主义核心价值观
            用户输入的密码 不能小于三位
                如果密码少于三位  提示用户 密码太短了

Description (******)


        校验数据通常是前后端都有校验
        但是前端校验可有可无 哪怕再牛逼
        后端也必须要有校验   反正一句话 前端可有不校验 后端必须校验!!!

analysis

1.搭建前端页面                                   >>>                  渲染页面
2.获取前端用户提交的数据校验                     >>>                  校验数据
3.对数据的校验的结果 展示到前端页面给用户查看    >>>                  展示错误信息

Front-end code

#reg.html部分代码
<form action="" method="post">
    <p>username:
        <input type="text" name="username">
        <span style="color: red">{{ back_dic.username }}</span>
    </p>
    <p>password:<input type="text" name="password">
    <span style="color: red">{{ back_dic.password }}</span>
    </p>
    <input type="submit">
</form>

Back-end code

def reg(request):
    back_dic = {"username":'','password':''}
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        if '西游记' in username:
            # 提示信息
            back_dic['username'] = '不符合社会主义核心价值观'
        if len(password) < 3:
            # 提示信息
            back_dic['password'] = '密码不能少于三位'
    return render(request,'reg.html',locals())

Two, forms a complete assembly writing

Writing and writing table class model is very similar, but there are constraints field forms assembly, model table class field is not binding

from django import forms
from django.forms import widgets  # 当你forms点不出来的时候 你可以手动导入一下
from django.core.validators import RegexValidator
class MyRegForm(forms.Form):#写一个继承了 forms.Form 的类
    username = forms.CharField(min_length=3,max_length=8,label='用户名', # 用户名最长八位最短三位
                               error_messages={
                                   'min_length':'用户名最短三位',
                                   'max_length':'用户名最长八位',
                                   'required':'用户名不能为空'
                               },initial='我是初始值',required=False,#允许不填
                               widget= widgets.TextInput(attrs={'class':'form-control others'})
                               )
    password = forms.CharField(min_length=3,max_length=8,label='密码',error_messages={
                                   'min_length':'密码最短三位',
                                   'max_length':'密码最长八位',
                                   'required':'密码不能为空'
                               },widget=widgets.PasswordInput())
    confirm_password = forms.CharField(min_length=3, max_length=8, label='确认密码', error_messages={
        'min_length': '确认密码最短三位',
        'max_length': '确认密码最长八位',
        'required': '确认密码不能为空'
    })
    email = forms.EmailField(label='邮箱',error_messages={
            'required':'邮箱不能为空',
            'invalid':'邮箱格式不正确'
    },required=False,widget=widgets.EmailInput(attrs={'class':'form-control'}))

Basic use

  1. The data to be verified, to the dictionary (usually when the parameter directly request.POST (a large dictionary)) way to pass a custom class, instantiation objects is generated

    form_obj = views.LoginForm({'username':'jason','password':'123','email':'123'})
  2. How to check whether all legal data

    form_obj.is_valid() ,只有所有的数据都符合要求 才会是True
  3. How to view the error cause

    form_obj.errors
    结果:
        'password': ['Ensure this value has at least 5 characters (it has 3).'], 
        'email': ['Enter a valid email address.']
  4. How to view data check by the

    form_obj.cleaned_data
    结果:
     {'username': 'jason'}
    

Three, forms a front end assembly rendering tag assembly

Description : forms rendering components will help you get user input (input, select, drop-down box ...) label the submit button requires you to manually write
the premise steps:

First generates an empty object , and the object is transmitted to the front page form_obj = MyForm() , and then select a way of rendering

#后端
def formmm(request):
    # 1.生成一个空的对象
    form_obj = MyRegForm()
    if request.method == 'POST':
        # 2.获取用户提交的数据
        # print(request.POST)  # request.POST  其实也可以看成是一个字典
        # 3.借助于form组件帮助我们校验
        form_obj = MyRegForm(request.POST)  # 由于request.POST其实就是一个大字典 所以直接当做参数传入即可
        # 4.判断用户输入的数据是否符合校验规则
        if form_obj.is_valid():
            return HttpResponse('你上传的数据没有问题')
    return render(request,'formmm.html',locals())

Rendering page (third recommendation)

<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_field in form_obj %}
    <p>{{ form_field.label }}{{ form_field }}</p>
{% endfor %}

Display error messages

默认是 ul 套 li ,可能有多个报错,我们索引取 0,取消它的 ul li 标签嵌套
<p>第三种渲染前端页面的方式:代码量和扩展性都很高(推荐使用)</p>
<form action="" method="post">
    {% for foo in form_obj %}
    <p>
        {{ foo.label }}:{{ foo }}
        <span style="color: red">{{ foo.errors.0 }}</span>
    </p>
    {% endfor %}
    <input type="submit">
</form>

Canceling the show error messages

只要加一参数novalidate
<form action="" method="post" novalidate>

Precautions

  • Components in forms to help you when rendering the page will render get user input label the submit button you need to manually add
  • annotation input label box without using the specified default field in the class, the first letter capitalized

Three, forms the other components of the knowledge

In the python console test

Test environment similar to django

Check data

form object instantiation parameters is a large dictionary

from app01 import views
# 1.给自定义的类传一个字典
obj = views.MyRegForm({'username':'jason','password':'12','email':'123'})
# 2.判断数据是否全部合法
obj.is_valid()  # 只有数据全部符合要求才会是True
Out[4]: False
# 3.查看符合校验规则的数据
obj.cleaned_data
Out[5]: {'username': 'jason'}
# 4.查看不符合条件的数据以及不符合的原因是什么
obj.errors
Out[6]: 
{
    'password': ['Ensure this value has at least 3 characters (it has 2).'],
    'email': ['Enter a valid email address.']
 }

# 5.校验数据的时候 默认情况下类里面所有的字段都必须传值
obj = views.MyRegForm({'username':'jason','password':'123'})
obj.is_valid()
Out[12]: False
obj.errors
Out[13]: {'email': ['This field is required.']}
# 6.默认情况下可以多传 但是绝对不能少传
obj = views.MyRegForm({'username':'jason','password':'1233','email':'[email protected]','xxx':'ooo'})
obj.is_valid()
Out[15]: True

form component data validation rules

  • Down sequentially from the value of the parity
  • The check is passed into cleaned_data
  • Validation failure into errors

note:

form 中所有的字段默认都是必须传值的(默认:required=True)

只要有一个字段不通过,form_obj.is_valid() 的结果就是 False,所有字段都校验通过了才会返回 True

校验数据的时候可以多传(多传的数据不会做任何的校验 >> > 不会影响 form 校验规则(所以 可以传 request.POST 直接当做参数,多余的不管))

Fourth, several other common field types

# 单选的radio框
    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()
    )
    # 多选的select框
    hobby1 = forms.MultipleChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
        label="爱好",
        initial=[1, 3],
        widget=forms.widgets.SelectMultiple()
    )
    # 单选的checkbox
    keep = forms.ChoiceField(
        label="是否记住密码",
        initial="checked",
        widget=forms.widgets.CheckboxInput()
    )
    # 多选的checkbox
    hobby2 = forms.MultipleChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
        label="爱好",
        initial=[1, 3],
        widget=forms.widgets.CheckboxSelectMultiple()
    )
    
    phone = forms.CharField(
        validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')],
    )

Five, forms components all built-in field types

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,              最大值
    min_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,            最大长度
    min_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,              初始值
    help_text='',              帮助提示
 
 
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类型

Six field parameter forms the common components

# 基本都渲染成 HTML 标签的属性(H5 对这些属性有支持)
max_length      最大长度
min_length      最小长度
required        是否必填
label           注释信息
initial         初始值(对应的是 value)

error_messages  报错信息
widget          控制标签的属性和样式(要手动导入,如果 forms.widget 点不出来 Widget,可以先导入 from django.forms import widget(有时候点不出来就需要自己写))
validators      正则(要手动导入,相当于钩子函数)
。。。

As a regular to restrain

#每个字段 还支持正则校验
        from django import forms
        from django.forms import Form
        from django.core.validators import RegexValidator
class MyForm(Form):
            user = forms.CharField(
                validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')],
            )

Seven, forms assembly hook function

Meaning : for the basic check (includes regular check) forms the field again for additional custom validation (customized business requirements)

  1. The basic steps

    • Gets the field inside the cleaned_data self.cleaned_data.get('字段名')
    • Field of the acquired verification customize if not password == confirm_password:
    • not match self.add_error('字段名', '报错提示信息')
    • return a return value return self.cleaned_data/username...
  2. Local hooks

     # 当你需要对某一个字段数据进行额外的一些列校验 你可以考虑使用钩子函数
    # 针对单个字段的  使用局部钩子
    #函数名:clean_formsField
    def clean_username(self):
     username = self.cleaned_data.get('username')
     if '西游记' in username:
     # 给username字段下面提示错误信息
         self.add_error('username','用户名不符合社会主义核心价值观')
     return username
    #针对某一个字段作额外校验(一定要返回该字段的值)
  3. Global hook

    # 针对多个字段的校验 使用全局钩子      eg:校验两次密码是否一致
    def clean(self):
     password = self.cleaned_data.get('password')
     confirm_password = self.cleaned_data.get('confirm_password')
     if not password == confirm_password:
         self.add_error('confirm_password','两次密码不一致')
     return self.cleaned_data
    

Eight, to modify the tip of the back-end style

如何改变input框的type属性值
    widget= widgets.TextInput()
    widget=widgets.PasswordInput()
如何让forms组件渲染出来的input框有form-control类属性
    widget= widgets.TextInput(attrs={'class':'form-control others'})  # 如果有多个类属性 空格隔开
    widget=widgets.PasswordInput(attrs={'class':'form-control others'})

Description : For details, see the wording of the second outline

Guess you like

Origin www.cnblogs.com/demiao/p/11761529.html