首页 > 其他分享 >forms组件

forms组件

时间:2024-03-28 20:01:50浏览次数:21  
标签:username None form forms length error 组件

forms组件

1.form介绍

  • form组件的主要功能如下:
    • 生成页面可用的HTML标签
    • 对用户提交的数据进行校验
    • 保留上次输入内容

2.需求案例

  • 写一个注册功能
    • 获取用户名和密码,利用form表单提交数据
    • 在后端判断用户名和密码是否符合一定的条件
      • 用户名中不能包含啦啦啦
      • 密码不能少于三位
    • 如果符合条件需要你将提示信息展示到前端页面

3.需求案例分析

3.1 手动渲染错误信息

  • 后端
def register(request):
  	# 自己定义的字典渲染到前端
    error_msg_dict = {}
    if request.method == 'POST':
        data = request.POST
        print(data)
        username = data.get("username")
        password = data.get("password")
        if username != 'serein':
            error = f"当前用户名{username}错误"
            error_msg_dict["username_error"] = error
        if password != '123':
            error = f"当前密码{password}错误"
            error_msg_dict["password_error"] = error
    return render(request, 'register.html', locals())
  • 前端
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="" method="post">
    <p>
        username:<input type="text" name="username">
        <span style="color: red">{{ error_msg_dict.username_error }}</span>
    </p>
    <p>
        password:<input type="text" name="password">
        <span style="color: red">{{ error_msg_dict.password_error }}</span>
    </p>
    <p>
        <input type="submit">
    </p>
</form>
</body>
</html>

3.2 form组件如何校验数据

3.2.1 编写表单类
  • 我们可以通过Django提供的Form类来自用生成上面的表单,不再需要手动在HTML中编写
  • 在你当前app内新建一个forms文件夹,在文件夹下面创建一个forms.py文件
  • 书写form表单类
# 导入模块
from django import forms

# 按照Django form组件的要求自己写一个类 MyForm
class UserForm(forms.Form):
    # username : 字符串类型  最小三位,最大八位
    username = forms.CharField(max_length=8, min_length=3)
    # # username : 字符串类型  最小三位,最大八位 : 字符串类型  最小三位,最大八位
    password = forms.CharField(max_length=8, min_length=3)
    # email : 必须符合邮箱格式  [email protected]
    email = forms.EmailField()
  • 注意事项
    • 提前导入forms模块
    • 所有的表单类都要继承forms.Form类
    • 每个表单字段都有自己的字段类型比如CharField,它们分别对应一种HTML语言中的<form>元素中的表单元素。这一点和Django模型系统的设计非常相似。
    • 例子中的label用于设置说明标签
    • max_length限制最大长度为8。它同时起到两个作用,一是在浏览器页面限制用户输入不可超过8个字符,二是在后端服务器验证用户输入的长度不可超过8。

3.3 基于form组件校验数据

  • 后端,需要导入form类

  • from app01.Formcontrol.UserForm import UserForm
    
def register(request):
    error_msg_dict = {}
    form_obj = UserForm()
    if request.method == 'POST':
        data = request.POST
        username = data.get("username")
        password = data.get("password")
        email = data.get("email")
        # 生成form对象
        form_obj = UserForm({"username": username, "password": password, "email": email})
        # 校验数据是否合法,is_valid
        form_obj.is_valid()
        # 查看合法的数据,cleaned_data
        print(f"合法数据{form_obj.cleaned_data}")
        # 查看不合法的数据,errors
        print(f"不合法数据{form_obj.errors}")

    return render(request, 'register.html', locals())

  • 前端
<form>  
		{{ form_obj }}
    <p>
        <input type="submit">
    </p>
</form>

4. FORM组件常用字段参数

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

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

class LoginForm(forms.Form):
    username = forms.CharField(
        min_length=8,
        label="用户名",
        initial="张三"  # 设置默认值
    )
    pwd = forms.CharField(min_length=6, label="密码")
4.3 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="密码")
4.4 password
class LoginForm(forms.Form):
    ...
    pwd = forms.CharField(
        min_length=6,
        label="密码",
        widget=forms.widgets.PasswordInput(attrs={'class': 'c1'}, render_value=True)
    )
4.5 radioSelect

单选按钮

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()
    )
4.6 单选Select
class LoginForm(forms.Form):
    ...
    hobby = forms.ChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),
        label="爱好",
        initial=3,
        widget=forms.widgets.Select()
    )
4.7 多选Select
class LoginForm(forms.Form):
    ...
    hobby = forms.MultipleChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),
        label="爱好",
        initial=[1, 3],
        widget=forms.widgets.SelectMultiple()
    )
4.8 单选框checkbox
class LoginForm(forms.Form):
    ...
    keep = forms.ChoiceField(
        label="是否记住密码",
        initial="checked",
        widget=forms.widgets.CheckboxInput()
    )
4.9 多选框checkbox
class LoginForm(forms.Form):
    ...
    hobby = forms.MultipleChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
        label="爱好",
        initial=[1, 3],
        widget=forms.widgets.CheckboxSelectMultiple()
    )
4.10 required 字段必填
class LoginForm(forms.Form):
    ...
    hobby = forms.MultipleChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
        label="爱好",
      	required = True
        initial=[1, 3],
        widget=forms.widgets.CheckboxSelectMultiple()
    )
4.11 choice字段注意事项
  • 在使用选择标签时
    • 需要注意choices的选项可以配置从数据库中获取
  • 但是由于是静态字段
    • 获取的值无法实时更新
    • 需要重写构造方法从而实现choice实时更新。
(1)方式一
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')
(2)方式二
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())  # 单选

5. 自定义字段校验

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

5.2 自定义验证函数

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'邮箱'}))

【补充】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类型

6. Form组件渲染HTML代码

  • forms组件只会帮我们渲染用户输入的标签(input/select...)

6.1 渲染方式一

(1)路由
# forms 组件渲染html标签
path(r'index/',views.index),
(2)后端代码
from django import forms


# 定义form类
class MyForm(forms.Form):
    # username : 字符串类型  最小三位,最大八位
    username = forms.CharField(max_length=8, min_length=3)
    # # username : 字符串类型  最小三位,最大八位 : 字符串类型  最小三位,最大八位
    password = forms.CharField(max_length=8, min_length=3)
    # email : 必须符合邮箱格式  [email protected]
    email = forms.EmailField()


def index(request):
    # (1)产生一个空对象
    form_obj = MyForm()
    # (2) 直接将空对象传递给前端页面
    return render(request,'index.html',locals())
(3)前端页面
<form action="" method="post">
    <p>第一种渲染方式</p>
    {{ form_obj }}
</form>
(4)渲染出的效果
  • 页面上会出现对应的HTML代码,但是是一开始没有的
<form action="" method="post">
    <p>第一种渲染方式</p>
    <label for="id_username">Username:</label><input type="text" name="username" maxlength="8" minlength="3"
                                                     required="" id="id_username">
    <label for="id_password">Password:</label><input type="text" name="password" maxlength="8" minlength="3"
                                                     required="" id="id_password">
    <label for="id_email">Email:</label><input type="email" name="email" required="" id="id_email">
</form>
(5)特点
  • 代码书写极少,封装程度太高,不便于后期拓展
  • 一般情况下用于本地测试使用

6.2 渲染方式二

(1)前端
<form action="" method="post">
    <p>第二种渲染方式</p>
    {{ form_obj.as_ul }}
</form>
(2)渲染到页面的效果
<form action="" method="post">
    <p>第二种渲染方式</p>
    <li><label for="id_username">Username:</label> <input type="text" name="username" maxlength="8" minlength="3"
                                                          required="" id="id_username"></li>
    <li><label for="id_password">Password:</label> <input type="text" name="password" maxlength="8" minlength="3"
                                                          required="" id="id_password"></li>
    <li><label for="id_email">Email:</label> <input type="email" name="email" required="" id="id_email"></li>
</form>
  • 该方法可以修改后端传入的属性值
# 定义form类
class MyForm(forms.Form):
    # username : 字符串类型  最小三位,最大八位
    username = forms.CharField(max_length=8, min_length=3, label="用户名")
    # # username : 字符串类型  最小三位,最大八位 : 字符串类型  最小三位,最大八位
    password = forms.CharField(max_length=8, min_length=3)
    # email : 必须符合邮箱格式  [email protected]
    email = forms.EmailField()


def index(request):
    # (1)产生一个空对象
    form_obj = MyForm()
    # (2) 直接将空对象传递给前端页面
    return render(request, 'index.html', locals())
  • 前端
<form action="" method="post">
    <p>第二种渲染方式</p>
    {#  对象点属性取到对应的属性值  #}
    {{ form_obj.username.label }} {{ form_obj.username }}

</form>
  • 前端页面展示效果
<form action="" method="post">


    <p>第二种渲染方式</p>


    用户名 <input type="text" name="username" maxlength="8" minlength="3" required="" id="id_username">

</form>
  • 特点
    • 可扩展性非常强
    • 但是需要书写复杂的代码
    • 一般情况下不用

6.3 渲染方式三(推荐使用)

  • 前端
<form action="" method="post">

    <p>推介使用第三种</p>
    {% for form in form_obj %}
        <p> {{ form.label }} : {{ form }}</p>
    {% endfor %}

</form>
  • 页面展示
<form action="" method="post">


    <p>推介使用第三种</p>

    <p> 用户名 : <input type="text" name="username" maxlength="8" minlength="3" required="" id="id_username"></p>

    <p> Password : <input type="text" name="password" maxlength="8" minlength="3" required="" id="id_password"></p>

    <p> Email : <input type="email" name="email" required="" id="id_email"></p>


</form>

7. 钩子函数

from django import forms


class UserForm(forms.Form):
    username = forms.CharField(
        max_length=6,
        min_length=3,
        required=True,
        label="用户名",
        error_messages={
            "max_length": "不能超过 6 位的最大长度",
            "min_length": "不能小于 3 位的最小长度"
        }
    )
    password = forms.CharField(
        max_length=4,
        min_length=2,
        label="密码",
    )

    # 先定义一个函数,函数名开头必须是clean_字段名,局部钩子
    def clean_username(self):
        print(f"这是在form的局部钩子中")
        print(self.cleaned_data)  # {'username': 'dd2'}
        # 先把需要校验的局部字段勾出来
        username = self.cleaned_data.get("username")
        # 进行字段的校验
        if "666" in username:
            self.add_error("username", "当前用户名不能包含 666 !")
        # 把校验后的数据扔回去
        return username
		
    # 全局钩子
    def clean(self):
        print(f"全局钩子")
        print(self.cleaned_data)
        username = self.cleaned_data.get("username")
        password = self.cleaned_data.get("password")
        # if len(username) == 4:
        #     self.add_error("username", "用户名不能是4位!")
        # if len(password) == 3:
        #     self.add_error("password", "密码不能是 3 位")
        return self.cleaned_data

标签:username,None,form,forms,length,error,组件
From: https://www.cnblogs.com/Formerly/p/18102503

相关文章

  • vue3 mitt事件总线,组件之间通信,通信范围不在局限于父子组件之间
    vue2使用的EventBus事件总线在vue3已经被弃用了;vue3使用的事件总线为mitt,可用父子组件,兄弟组件之间通信我使用的方法如下新建一个mitt.ts文件保存以下内容importmitts,{Emitter}from"mitt";//定义类型别名,因全局使用并且需要自定义事件名称,所以使用索引签名......
  • Vue 自定义组件库通过配置调整样式?
      在Vue自定义组件库中,通常可以通过配置来调整样式。为了实现这一点,你可以定义一组样式相关的配置项,并在组件内部使用这些配置项来动态地设置样式。以下是一个简单的示例,演示了如何通过配置调整组件的样式。自定义组件(CustomComponent.vue)<template><div:style......
  • ONLYOFFICE 文档 Vue 组件
    ONLYOFFICE文档Vue组件ONLYOFFICEDocsVue.js 组件 集成ONLYOFFICEDocs到 Vue.js 项目。先决条件此过程需要 Node.js(和npm)。使用ONLYOFFICE文档编辑器创建演示Vue.js应用程序此过程创建一个基本Vue.js应用程序 并在其中安装ONLYOFFICE文档编辑器。......
  • auth组件
      我们需要实现包括用户注册、用户登录、用户认证、注销、修改密码等功能,内置了强大的用户认证系统--auth,是一个app 其实我们在创建好一个django项目之后直接执行数据库迁移命令会自动生成很多表 django_session auth_userdjango在启动之后就可以直接访问admin路由,需要输......
  • 在Vue项目中使用Vuex进行状态管理是一种常见做法。下面是一个简单的示例,展示了如何创
    步骤1:创建VuexStore首先,你需要创建一个Vuexstore。通常,这是在你的项目的store目录下完成的。//store.jsimportVuefrom'vue';importVuexfrom'vuex';Vue.use(Vuex);conststore=newVuex.Store({state:{count:0},mutations:{increment(......
  • 前端组件wolfTable中关于表格冻结部分的说明
    在wolfTable中,可以使用冻结表格,这样就可以达成类似下拉滚动条的时候始终显示前几行的功能。 在这里,用组件自带的案例代码来做说明import'@wolf-table/table/dist/table.min.css';importTablefrom"@wolf-table/table";constt=Table.create('#table',()=>14......
  • vue3子组件给父组件传参,父组件给子组件传参,在父组件中直接调用子组件中的某个方法
    vue3子组件给父组件传参,父组件给子组件传参,在父组件中直接调用子组件中的某个方法1、子传父,以传递id为例子:constemit=defineEmits(['passId']);//在需要传递的参数的地方写,id为需要传递的参数emit('passId',id); 父://引入子组件constSonPage=defineAsyncCo......
  • 深入浅出:探索Hadoop生态系统的核心组件与技术架构
    目录前言HDFSYarnHiveHBaseSpark及SparkStreaming书本与课程推荐关于作者:推荐理由:作者直播推荐:前言进入大数据阶段就意味着 进入NoSQL阶段,更多的是面向OLAP场景,即数据仓库、BI应用等。大数据技术的发展并不是偶然的,它的背后是对于成本的考量。集中式数据库或......
  • 「DevExpress中文教程」如何将DevExtreme JS HTML编辑器集成到WinForms应用
    在本文中我们将演示一个混合实现:如何将webUI工具集成到WinForms桌面应用程序中。具体来说,我们将把DevExtremeJavaScriptWYSIWYGHTML编辑器(作为DevExtreme UI组件套件的一部分发布的组件)集成到WindowsForms应用程序中。获取DevExtremev23.2正式版下载DevExpress技术交......
  • 【Vue】 签名组件
    一、需求背景:检查业务,检查完成后,执行人需要签字证明检查完成 二、实现效果: 三、技术实现通过canvas转换成blob对象,可以上传到文件服务,或者是下载另存为到本地磁盘注意重点,canvas的样式的宽高和dom对象宽高一定要一致才可以,否则无法在面板绘制线条!<template><el-dia......