015---Django的forms组件

Form介绍

我们之前在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标签把它们包起来。

与此同时我们在好多场景下都需要对用户的输入做校验,比如校验用户是否输入,输入的长度和格式等正不正确。如果用户输入的内容有错误就需要在页面上相应的位置显示对应的错误信息.。

Django form组件就实现了上面所述的功能。

总结一下,其实form组件的主要功能如下:

  • 生成页面可用的HTML标签
  • 对用户提交的数据进行校验
  • 保留上次输入内容

先在应用目录下my_forms.py定义好一个UserForm类

 1 from django import forms
 2 from django.forms import widgets
 3
 4     class UserForm(forms.Form):
 5         username = forms.CharField(min_length=4, label=‘用户名‘,
 6                                    widget=widgets.TextInput(attrs={"class": "form-control"}),
 7                                    error_messages={
 8                                        "required": "用户名不能为空",
 9                                    })
10         pwd = forms.CharField(min_length=4, label=‘密码‘,
11                               error_messages={
12                                   "required": "密码不能为空",
13                               },
14                               widget=widgets.PasswordInput(attrs={"class": "form-control"}))
15         r_pwd = forms.CharField(min_length=4, label=‘确认密码‘,
16                                 widget=widgets.PasswordInput(attrs={"class": "form-control"}),
17                                 error_messages={
18                                     "required": "密码不能为空",
19                                 })
20         email = forms.EmailField(label=‘邮箱‘,
21                                  widget=widgets.EmailInput(attrs={"class": "form-control"}),
22                                  error_messages={
23                                      "required": ‘邮箱不能为空‘,
24                                      "invalid": "邮箱格式错误",
25                                  })
26         tel = forms.CharField(label=‘手机号‘,
27                               widget=widgets.TextInput(attrs={"class": "form-control"}),
28                               )

再写一个视图函数:

 1 在写一个视图函数
 2     def reg(request):
 3         form = UserForm()
 4         if request.method == "POST":
 5             print(request.POST)
 6             # 实例化form对象的时候,把post提交过来的数据直接传进去
 7             form = UserForm(request.POST)  # form表单的name属性值应该与forms组件的字段名称一致
 8             if form.is_valid():
 9                 print(form.cleaned_data)
10                 return HttpResponse(‘注册成功‘)
11         return render(request, ‘reg.html‘, locals())

login.html

 2     <!DOCTYPE html>
 3     <html lang="zh_CN">
 4     <head>
 5         <meta charset="UTF-8">
 6         <meta http-equiv="x-ua-compatible" content="IE=edge">
 7         <meta name="viewport" content="width=device-width, initial-scale=1">
 8         <title>注册</title>
 9     </head>
10     <body>
11
12     <h3>传统form表单</h3>
13     <form action="" method="post">
14         {% csrf_token %}
15         <p>用户名:<input type="text" name="username"></p>
16         <p>密码:<input type="password" name="pwd"></p>
17         <p>确认密码:<input type="password" name="r_pwd"></p>
18         <p>邮箱:<input type="email" name="email"></p>
19         <p>手机号:<input type="tel" name="tel"></p>
20         <p><input type="submit" value="提交"></p>
21     </form>
22
23     <h3>forms组件渲染方式1</h3>
24     <form action="" method="post" novalidate>
25         {% csrf_token %}
26         <p>{{ form.username.label }}:{{ form.username }} <span>{{ form.username.errors.0 }}</span></p>
27         <p>密码:{{ form.pwd }}
28             <span>{{ form.pwd.errors.0 }}</span></p>
29         <p>确认密码:{{ form.r_pwd }}
30             <span>{{ form.r_pwd.errors.0 }}</span></p>
31         <p>邮箱:{{ form.email }}
32             <span>{{ form.email.errors.0 }}</span></p>
33         <p>手机号:{{ form.tel }}
34             <span>{{ form.tel.errors.0 }}</span></p>
35         <p><input type="submit" value="提交"></p>
36     </form>
37
38      <h3>forms组件渲染标签方式2</h3>
39         <form action="" method="post" novalidate>
40             {% csrf_token %}
41             {% for field in form %}
42                 <div class="form-group clearfix">
43                     <label for="">{{ field.label }}</label>
44                     {{ field }}
45                     <span style="color: red" class="pull-right">{{ field.errors.0 }}</span>
46                     {% if field.name == ‘r_pwd‘ %}
47                         <span style="color: red" class="pull-right">{{ errors.0 }}</span>
48                     {% endif %}
49                 </div>
50             {% endfor %}
51             <input type="submit" value="注册" class="btn btn-default pull-right">
52         </form>
53
54
55
56     <h3>forms组件渲染标签方式3   不推荐使用</h3>
57     <form action="" method="post">
58         {% csrf_token %}
59         {{ form.as_p }}
60         <input type="submit" value="注册">
61     </form>
62     </body>
63     </html>

看网页效果发现 也验证了form的功能:
• 前端页面是form类的对象生成的                 
                    -->生成HTML标签功能

当用户名和密码输入为空或输错之后 页面都会提示        -->用户提交校验功能
• 当用户输错之后 再次输入 上次的内容还保留在input框 
 -->保留上次输入内容

Form那些事儿

常用字段与插件

创建Form类时,主要涉及到 【字段】 和 【插件】,字段用于对用户请求数据的验证,插件用于自动生成HTML;

initial

初始值,input框里面的初始值。

class LoginForm(forms.Form):
    username = forms.CharField(
        min_length=8,
        label="用户名",
        initial="张三"  # 设置默认值
    )
    pwd = forms.CharField(min_length=6, label="密码")

error_messages

重写错误信息。

class LoginForm(forms.Form):
    username = forms.CharField(
        min_length=8,
        label="用户名",
        initial="张三",
        error_messages={
            "required": "不能为空",
            "invalid": "格式错误",
            "min_length": "用户名最短8位"
        }
    )
    pwd = forms.CharField(min_length=6, label="密码")

password

class LoginForm(forms.Form):
    ...
    pwd = forms.CharField(
        min_length=6,
        label="密码",
        widget=forms.widgets.PasswordInput(attrs={‘class‘: ‘c1‘}, render_value=True)
    )

radioSelect

单radio值为字符串

class LoginForm(forms.Form):
    username = forms.CharField(
        min_length=8,
        label="用户名",
        initial="张三",
        error_messages={
            "required": "不能为空",
            "invalid": "格式错误",
            "min_length": "用户名最短8位"
        }
    )
    pwd = forms.CharField(min_length=6, label="密码")
    gender = forms.fields.ChoiceField(
        choices=((1, "男"), (2, "女"), (3, "保密")),
        label="性别",
        initial=3,
        widget=forms.widgets.RadioSelect()
    )

单选Select

class LoginForm(forms.Form):
    ...
    hobby = forms.fields.ChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),
        label="爱好",
        initial=3,
        widget=forms.widgets.Select()
    )

多选Select

class LoginForm(forms.Form):
    ...
    hobby = forms.fields.MultipleChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),
        label="爱好",
        initial=[1, 3],
        widget=forms.widgets.SelectMultiple()
    )

单选checkbox

class LoginForm(forms.Form):
    ...
    keep = forms.fields.ChoiceField(
        label="是否记住密码",
        initial="checked",
        widget=forms.widgets.CheckboxInput()
    )

多选checkbox

class LoginForm(forms.Form):
    ...
    hobby = forms.fields.MultipleChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
        label="爱好",
        initial=[1, 3],
        widget=forms.widgets.CheckboxSelectMultiple()
    )

关于choice的注意事项:

在使用选择标签时,需要注意choices的选项可以从数据库中获取,但是由于是静态字段 ***获取的值无法实时更新***,那么需要自定义构造方法从而达到此目的。

方式一:

from django.forms import Form
from django.forms import widgets
from django.forms import fields

class MyForm(Form):

    user = fields.ChoiceField(
        # choices=((1, ‘上海‘), (2, ‘北京‘),),
        initial=2,
        widget=widgets.Select
    )

    def __init__(self, *args, **kwargs):
        super(MyForm,self).__init__(*args, **kwargs)
        # self.fields[‘user‘].choices = ((1, ‘上海‘), (2, ‘北京‘),)
        # 或
        self.fields[‘user‘].choices = models.Classes.objects.all().values_list(‘id‘,‘caption‘)

方式二:

from django import forms
from django.forms import fields
from django.forms import models as form_model

class FInfo(forms.Form):
    authors = form_model.ModelMultipleChoiceField(queryset=models.NNewType.objects.all())  # 多选
    # authors = form_model.ModelChoiceField(queryset=models.NNewType.objects.all())  # 单选

Django Form所有内置字段

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类型

Django Form内置字段

校验

方式一:

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开头‘)],
    )

方式二:

import re
from django.forms import Form
from django.forms import widgets
from django.forms import fields
from django.core.exceptions import ValidationError

# 自定义验证规则
def mobile_validate(value):
    mobile_re = re.compile(r‘^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$‘)
    if not mobile_re.match(value):
        raise ValidationError(‘手机号码格式错误‘)

class PublishForm(Form):
    title = fields.CharField(max_length=20,
                            min_length=5,
                            error_messages={‘required‘: ‘标题不能为空‘,
                                            ‘min_length‘: ‘标题最少为5个字符‘,
                                            ‘max_length‘: ‘标题最多为20个字符‘},
                            widget=widgets.TextInput(attrs={‘class‘: "form-control",
                                                          ‘placeholder‘: ‘标题5-20个字符‘}))

    # 使用自定义验证规则
    phone = fields.CharField(validators=[mobile_validate, ],
                            error_messages={‘required‘: ‘手机不能为空‘},
                            widget=widgets.TextInput(attrs={‘class‘: "form-control",
                                                          ‘placeholder‘: u‘手机号码‘}))

    email = fields.EmailField(required=False,
                            error_messages={‘required‘: u‘邮箱不能为空‘,‘invalid‘: u‘邮箱格式错误‘},
                            widget=widgets.TextInput(attrs={‘class‘: "form-control", ‘placeholder‘: u‘邮箱‘}))

方式三:

 1     def clean(self):
 2         pwd = self.cleaned_data.get(‘pwd‘)
 3         r_pwd = self.cleaned_data.get(‘r_pwd‘)
 4         print(pwd, r_pwd)
 5         if pwd and r_pwd:
 6             if pwd == r_pwd:
 7                 return self.cleaned_data
 8             raise ValidationError(‘两次密码不一致‘)
 9         else:
10             return self.cleaned_data
11
12     def clean_username(self):
13         val = self.cleaned_data.get(‘username‘)
14         user = UserInfo.objects.filter(name=val)
15         if not user:
16             return val
17         else:
18             raise ValidationError("用户名已注册")
19
20     def clean_tel(self):
21         val = self.cleaned_data.get(‘tel‘)
22         if len(val) == 11:
23             return val
24         raise ValidationError(‘手机号格式错误‘)

总结:

 1  ‘‘‘
 2     局部钩子:
 3         1、is_valid()
 4         2、self.errors
 5         3、self.full_clean()
 6         4、self._clean_fields()  校验每一个字段
 7         5、for 循环每一个字段名、验证规则对象
 8         6、
 9             验证通过:
10                 value = field.clean(value)
11                 self.cleaned_data[name] = value             添加到clean_data中
12
13                 利用反射、钩子自定义验证规则
14                 hasattr(self, ‘clean_%s‘ % name)            写自定义方法
15                 value = getattr(self, ‘clean_%s‘ % name)()  执行自定义方法
16                     pass:
17                         self.cleaned_data[name] = value     添加到clean_data中
18                     no_pass:
19                         raise ValidationError(msg)          抛出异常
20             不通过:
21                 raise ValidationError(msg)
22
23
24     全局钩子:
25         1、is_valid()
26         2、self.errors
27         3、self.full_clean()
28         4、self._clean_form()    全部字段调用完成之后  调用
29         5、self.clean()  重写clean方法
30         6、全局钩子错误:forms.errors.get("__all__")
31
32     ‘‘‘

原文地址:https://www.cnblogs.com/xjmlove/p/9927527.html

时间: 2024-10-30 15:56:17

015---Django的forms组件的相关文章

Django - 基于forms组件和Ajax实现注册登录 - FileField字段 - Media配置

一.基于forms组件的注册页面设计 点击头像==点击input 头像预览: 修改  获取用户选中的文件对象:获取文件对象的路径:修改img标签的src属性,让src=文件对象路径. register.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link

Django之forms组件使用

注册功能 1.渲染前端标签获取用户输入 >>> 渲染标签 2.获取用户输入传递到后端校验 >>> 校验数据 3.校验未通过展示错误信息 >>> 展示信息 校验数据(前后端都可以校验) 校验前端后端都可以做,但是前端可以不做,后端必须得做!!! django form组件 1.渲染标签 2.校验数据 3.展示信息 校验数据 第一步需要在views中写一个form类 from django import forms class MyForm(forms.F

django(forms组件、cookies与session)

一.forms组件 1.功能 - 渲染页面 - 校验数据 - 展示信息 需要先写一个类,该类类似于models中的表类 from django import forms class MyRegForm(forms.Form): # 用户名最少3位最多8位 username = forms.CharField(max_length=8,min_length=3) password = forms.CharField(max_length=8,min_length=3) # email字段必须填写符

Django之forms组件

一.校验数据功能 我们在写注册页面时,之前只是提交了数据,然后就保存了数据,后端根本就没有对数据进行校验,比如价格写的不是纯数字也让保存,这肯定是不行的,在前端是可以校验的,但我们不能只依靠前端验证,万一前端不校验,那整个过程就没校验了,所以,不管前端有没有校验,我们后端都应该进行验证. 现在注册页面要向我提交三个数据,用户名.密码.邮箱,当它提交过来后,首先我要对数据进行校验,根据数据的校验结果然后再决定保存还是给前端返回错误信息. views.py from django import fo

CSIC_716_20200113【Django入门---forms组件、session和cookie、登录认证装饰器】

forms组件 forms组件的功能:1.渲染前端页面,不用在前端手写forms表单了,不过只会渲染用户输入(输入.选择.下拉.文件)的标签,不渲染按钮以及form表单标签,.2.后端能进行非常规范的数据合法性校验3.展示校验之后的合法性信息. 使用方法:1.定义一个自定义forms类 form组件的前端渲染方式 效果差不多 哈哈哈哈 顶 原文地址:https://www.cnblogs.com/csic716/p/12189236.html

Django forms组件【对form舒心l了】

目录 Django forms组件 bound and unbound form instance forms渲染有关 隐藏一个字段,不渲染它 form 校验 form类 ModelForm 利用ModelForm关键就在于model's field mapping to form's field ModelForm.save() 详解 class Meta !!!重写覆盖默认的modelField字段(即自定义一些modelform属性) form有关多选择Field的使用 form's fi

Django组件—forms组件

forms组件: 校验字段功能: 针对一个实例:注册用户. 模型:models.py class UserInfo(models.Model): name=models.CharField(max_length=32) pwd=models.CharField(max_length=32) email=models.EmailField() tel=models.CharField(max_length=32) 模板:register.html <!DOCTYPE html> <html

12.Django组件-forms组件

forms组件 校验字段功能 针对一个实例:注册用户讲解. 模型:models.py class UserInfo(models.Model): name=models.CharField(max_length=32) pwd=models.CharField(max_length=32) email=models.EmailField() tel=models.CharField(max_length=32) 模板: register.html: <!DOCTYPE html> <ht

Django组件——forms组件

一,forms组件: 校验字段功能针对一个实例:注册用户讲解.模型:models.py class UserInfo(models.Model): name=models.CharField(max_length=32) pwd=models.CharField(max_length=32) email=models.EmailField() tel=models.CharField(max_length=32) 模板: register.html: <!DOCTYPE html> <h

Django组件:forms组件

针对"注册用户"示例: 一.校验字段功能 1.模型:models.py class UserInfo(models.Model): name=models.CharField(max_length=32) pwd=models.CharField(max_length=32) email=models.EmailField() tel=models.CharField(max_length=32) 2.模板:register.html: <!DOCTYPE html> &l