forms组件(钩子函数(局部钩子、全局钩子)、三种页面的渲染方式、数据校验的使用)、form组件的参数以及单选多选形式

一、form是组件

后端代码

python 复制代码
from django.shortcuts import render, redirect, HttpResponse


def ab_form(request):
    back_dict = {'username': '', 'password': ''}
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')

        if '金瓶梅' in username:
            back_dict['username'] = '不符合规范'
        if len(password) < 3 and len(password) > 20:
            back_dict['password'] = '密码的长度只能介于3位到20位的区间'

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


from django import forms


class MyForm(forms.Form):
    username = forms.CharField(min_length=3, max_length=8, label='用户名',
                               error_messages={
                                   'min_length': '用户名最少3位',
                                   'max_length': '用户名最大8位',
                                   'required': '用户名不能为空',
                               })
    password = forms.CharField(min_length=3, max_length=8, label='密码',
                               error_messages={
                                   'min_length': '密码最少3位',
                                   'max_length': '密码最大8位',
                                   'required': '密码不能为空',
                               })
    confirm_password = forms.CharField(min_length=3, max_length=8, label='确认密码',
                               error_messages={
                                   'min_length': '确认密码最少3位',
                                   'max_length': '确认密码最大8位',
                                   'required': '确认密码不能为空',
                               })
    # email字段必须符合邮箱格式:xxx@xx.com
    email = forms.EmailField(label='邮箱',
                             error_messages={
                                   'invalid': '邮箱格式不正确',
                                   'required': '密码不能为空',
                               })

    '''
        form_obj = views.MyForm({'username': 'json', 'password': 123, 'email': '123'})
        # 校验数据是否合法
        form_obj.is_valid()  False
        
        form_obj = views.MyForm({'username': 'json', 'password': 123, 'email': 'xx@123.com'})
        form_obj.is_valid()   True
       
        # 校验合法的数据有哪些
        form_obj.cleaned_data
        {'username': 'json', 'password': '123', 'email': 'xx@123.com'}
        
        form_obj = views.MyForm({'username': 'json', 'password': 123, 'email': '123'})
        form_obj.is_valid()  False
        
        form_obj.cleaned_data
        {'username': 'json', 'password': '123'}
        
        # 把不合法的数据找出来
        form_obj.errors  {'email': ['输入一个有效的 Email 地址。']}
        
        form_obj = views.MyForm({'username': 'json', 'password': 123})
        form_obj.is_valid()  False
        
        form_obj.errors
        {'email': ['这个字段是必填项。']}
        
    '''

    # 局部钩子
    def clean_username(self):
        # 获取到用户名
        username = self.cleaned_data.get('username')
        if '666' in username:
            # 提示前端展示错误信息
            self.add_error('username', '只含有666不行')
        # 将钩子函数钩取出来的数据再放回去
        return username

    # 全局钩子
    def clean_password(self):
        # 获取密码和确认密码
        password = self.cleaned_data.get('password')
        confirm_password = self.cleaned_data.get('confirm_password')
        if not confirm_password == password:
            self.add_error('confirm_password', '两次密码不一致')
        # 将钩子函数钩取出来的数据再放回去
        return self.cleaned_data

    '''
        钩子函数(HOOK):在特定的节点自动触发完成响应的操作
            在forms组件中有两类钩子
            1.局部钩子:
                当你需要给单个字段增加校验规则的时候可以使用
            2.全局钩子:
                当你需要给多个字段增加校验规则的时候可以使用

            案例:
                1.校验用户名中不能含有666 只是校验username字段,局部钩子
                2.校验密码和确认密码是否一致 password和confirm两个字段  全局钩子
        '''


def index(request):
    # 1.先产生一个空对象
    # 里面的label属性默认展示的是类中定义的字段首字母大写的形式,
    # 也可以自行修改,如:label='用户名'
    form_obj = MyForm()
    if request.method == 'POST':

        # 获取用户数据并且校验
        '''
            1.获取数据繁琐
            2.校验数据需要构造成字典的格式传入才行
            PS:但是 request.POST 可以看成是一个字典
        '''
        # 3.校验数据
        form_obj = MyForm(request.POST)
        # 4.判断数据是否合法
        if form_obj.is_valid():
            # 5.若合法,操作数据库,存储数据
            return HttpResponse('OK')

        # 不合法,如何将错误信息展示到前端?

    # 2.直接将该空对象传递给html页面

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

2.前端值index

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    {% load static %}
    <script src="{% static 'js/jquery.min.js' %}"></script>
    <link href="{% static 'bootstrap/css/bootstrap.min.css' %}" rel="stylesheet">
    <script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
    <script src="{% static 'layer/layer.js' %}"></script>

</head>
<body>

<form action="" method="post" novalidate>
    <p>第一种页面渲染方式: 代码书写少,封装程度太高了,不便于后续的扩展,一般只在本地测试使用</p>
{#    {{ form_obj.as_p }}#}

    <p>第二种页面渲染方式:可扩展性很强,但是需要书写的代码太多,一般情况下不用</p>
{#    {{ form_obj.as_ul }}#}
{#    <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>
{#    {{ form_obj.as_table }}#}
    {% for form in form_obj %}
        <p>
            {{ form.label }}:{{ form}}
            <span style="color: red">{{ form.errors.0 }}</span>
        </p>
    {% endfor %}
    <input type="submit" class="btn btn-info">
    
</form>


</body>
</html>

3.前端之ab_form

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    {% load static %}
    <script src="{% static 'js/jquery.min.js' %}"></script>
    <link href="{% static 'bootstrap/css/bootstrap.min.css' %}" rel="stylesheet">
    <script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
    <script src="{% static 'layer/layer.js' %}"></script>

</head>
<body>

<form action="" method="post">
    <div class="container">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <p>username :
                    <input type="text" name="username">
                    <span style="color: darkred">{{ back_dict.username }}</span>
                </p>
                <p>password:
                    <input type="password" name="password">
                    <span style="color: darkred">{{ back_dict.password }}</span>
                </p>
                <input type="submit" class="btn btn-info">
            </div>
        </div>
    </div>


</form>

</body>
</html>

4.form组件的参数以及单选多选形式

python 复制代码
class MyForm(forms.Form):
    username = forms.CharField(min_length=3, max_length=8,
                               label='用户名',
                               initial='lin',
                               required=False,
                               error_messages={
                                   'min_length': '用户名最少3位',
                                   'max_length': '用户名最大8位',
                                   'required': '用户名不能为空',
                               },
                               widget=forms.widgets.TextInput(attrs={'class': 'form-control', 'username': 'lin'})
                               )
    password = forms.CharField(min_length=3, max_length=8, label='密码',
                               error_messages={
                                   'min_length': '密码最少3位',
                                   'max_length': '密码最大8位',
                                   'required': '密码不能为空',
                               },
                               widget=forms.widgets.PasswordInput()
                               )
    confirm_password = forms.CharField(min_length=3, max_length=8, label='确认密码',
                               error_messages={
                                   'min_length': '确认密码最少3位',
                                   'max_length': '确认密码最大8位',
                                   'required': '确认密码不能为空',
                               },
                               widget=forms.widgets.PasswordInput()
                               )
    # email字段必须符合邮箱格式:xxx@xx.com
    email = forms.EmailField(label='邮箱',
                             error_messages={
                                   'invalid': '邮箱格式不正确',
                                   'required': '密码不能为空',
                               },
                             widget=forms.widgets.EmailInput()
                             )
    # 还支持正则校验
    phone = forms.CharField(
        validators=[
            RegexValidator(r'^[0-9]+$', '请输入数字'),
            RegexValidator(r'^159[0-9]+$', '数字必须以159开头')
        ],
    )
    # 选择
    gender = forms.ChoiceField(
        choices=((1, '男'), (2, '女'), (3, '保密')),
        label='性别',
        initial=3,
        widget=forms.widgets.RadioSelect()
    )
    # 多选
    hobby = forms.ChoiceField(
        choices=((1, '篮球'), (2, '足球'), (3, '双色球')),
        label='爱好',
        initial=3,
        widget=forms.widgets.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()
    )

    '''
    forms组件其他参数及补充知识点:
        label 字段名
        error_messages  自定义报错信息
        invalid    邮箱格式提示信息
        initial    设置默认值
        required   控制字段是否必填
        
        
    字段没有样式:
        针对不同类型的input如何修改?
            通过 widget
            如:
            widget=forms.widgets.TextInput()
            widget=forms.widgets.TextInput(attrs={'class': 'form-control', 'username': 'lin'})
                注意:需要什么样式,自行添加, 若是多个属性值,直接空格隔开即可
            widget=forms.widgets.PasswordInput()
            widget=forms.widgets.EmailInput()
        text
        password
        date
        radio
        checkbox
        ...
        
    '''


    '''
        form_obj = views.MyForm({'username': 'json', 'password': 123, 'email': '123'})
        # 校验数据是否合法
        form_obj.is_valid()  False
        
        form_obj = views.MyForm({'username': 'json', 'password': 123, 'email': 'xx@123.com'})
        form_obj.is_valid()   True
       
        # 校验合法的数据有哪些
        form_obj.cleaned_data
        {'username': 'json', 'password': '123', 'email': 'xx@123.com'}
        
        form_obj = views.MyForm({'username': 'json', 'password': 123, 'email': '123'})
        form_obj.is_valid()  False
        
        form_obj.cleaned_data
        {'username': 'json', 'password': '123'}
        
        # 把不合法的数据找出来
        form_obj.errors  {'email': ['输入一个有效的 Email 地址。']}
        
        form_obj = views.MyForm({'username': 'json', 'password': 123})
        form_obj.is_valid()  False
        
        form_obj.errors
        {'email': ['这个字段是必填项。']}
        
    '''

    # 局部钩子
    def clean_username(self):
        # 获取到用户名
        username = self.cleaned_data.get('username')
        if '666' in username:
            # 提示前端展示错误信息
            self.add_error('username', '只含有666不行')
        # 将钩子函数钩取出来的数据再放回去
        return username

    # 全局钩子
    def clean_password(self):
        # 获取密码和确认密码
        password = self.cleaned_data.get('password')
        confirm_password = self.cleaned_data.get('confirm_password')
        if not confirm_password == password:
            self.add_error('confirm_password', '两次密码不一致')
        # 将钩子函数钩取出来的数据再放回去
        return self.cleaned_data

    '''
        钩子函数(HOOK):在特定的节点自动触发完成响应的操作
            在forms组件中有两类钩子
            1.局部钩子:
                当你需要给单个字段增加校验规则的时候可以使用
            2.全局钩子:
                当你需要给多个字段增加校验规则的时候可以使用

            案例:
                1.校验用户名中不能含有666 只是校验username字段,局部钩子
                2.校验密码和确认密码是否一致 password和confirm两个字段  全局钩子
        '''
相关推荐
极梦网络无忧4 小时前
OpenClaw 基础使用说明(中文版)
python
codeJinger4 小时前
【Python】操作Excel文件
python·excel
XLYcmy4 小时前
一个针对医疗RAG系统的数据窃取攻击工具
python·网络安全·ai·llm·agent·rag·ai安全
Islucas5 小时前
Claude code入门保姆级教程
python·bash·claude
萝卜白菜。5 小时前
TongWeb7.0相同的类指明加载顺序
开发语言·python·pycharm
赵钰老师5 小时前
【ADCIRC】基于“python+”潮汐、风驱动循环、风暴潮等海洋水动力模拟实践技术应用
python·信息可视化·数据分析
爬山算法5 小时前
MongoDB(80)如何在MongoDB中使用多文档事务?
数据库·python·mongodb
YuanDaima20486 小时前
基于 LangChain 1.0 的检索增强生成(RAG)实战
人工智能·笔记·python·langchain·个人开发·langgraph
RopenYuan7 小时前
FastAPI -API Router的应用
前端·网络·python