• forms组件


    一、初始forms组件

      小需求:

        我们写一个注册页面 获取用户输入的用户名与密码,用户点击注册发送到后端做用户名密码的校验

        用户名中不能包含金瓶mei         如果包含报错提示不符合社会主义核心价值观

        密码可不能为空                       如果为空报错提示密码不能为空 你个DSB

    - 代码演示

    """day56 URL Configuration
    
    The `urlpatterns` list routes URLs to views. For more information please see:
        https://docs.djangoproject.com/en/1.11/topics/http/urls/
    Examples:
    Function views
        1. Add an import:  from my_app import views
        2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
    Class-based views
        1. Add an import:  from other_app.views import Home
        2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
    Including another URLconf
        1. Import the include() function: from django.conf.urls import url, include
        2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
    """
    from django.conf.urls import url
    from django.contrib import admin
    from app01 import views
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^register/', views.register),
    ]
    urls.py
    from django.shortcuts import render, HttpResponse, redirect, reverse
    
    # Create your views here.
    
    def register(request):
        error_dict = {'username': '', 'password': ''}
        if request.method == 'POST':
            username = request.POST.get('username')
            password = request.POST.get('password')
            if '金瓶mei' in username:
                # 提示报错信息
                error_dict['username'] = '不符合社会主义核心价值观'
            if not password:
                # 提示报错信息
                error_dict['password'] = '密码不能为空, 你个DSB'
        return render(request, 'register.html', locals())
    Views.py
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
        <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
        <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
    
    </head>
    <body>
    <form action="" method="post">
        <p>username:
            <input type="text" name="username">
            <span style="color: red">{{ error_dict.username }}</span>
        </p>
        <p>password:
            <input type="text" name="password">
            <span style="color: red">{{ error_dict.password }}</span>
        </p>
        <input type="submit">
    </form>
    </body>
    </html>
    register.html

    - 效果图

    其实在这整个过程中 我们自己做了这么几件事

      1、手写获取用户输入的前端页面代码                   (渲染标签)

      2、后端获取用户数据并做合法性校验      (校验数据)

      3、将校验之后的结果渲染到前端页面      (渲染信息)

    那么有没有这么一种能够帮我们完成上面是三件事,其实forms组件就可以帮我们完成这三件事

    forms组件可以:

      1、渲染标签

      2、校验数据

      3、渲染信息

    二、forms组件之校验数据

    1、测试环境

      注意:我们在使用forms组件去校验数据的前提(准备工作),需要我们先写一个类之后才可以去校验数据,这里需要先导入一个模块form django import forms

    from django import forms    # 写之前需要先导入一个模块
    
    
    class MyRegForm(forms.Form):
        username = forms.CharField(max_length=8, min_length=3)   # 限制你的用户名最大为8位数,最小为3位数
        password = forms.CharField(max_length=8, min_length=3)
        email = forms.EmailField()   # 限制必须为符合邮箱类型的数据

    之前我们已经介绍过了如何去单独的去测试某一个数据或文件,是需要我们去配置一个测试环境的,接下来再来介绍一下一个pycharm自带的测试环境,更为简洁

     2、如何校验数据

    # 1.传入待校验的数据  用自己写的类 传入字典格式的待校验的数据
                form_obj = views.MyRegForm({'username':'yafeng','password':'12','email':'123456'})
                # 2.判断数据是否符合校验规则
                form_obj.is_valid()  # 该方法只有在所有的数据全部符合校验规则才会返回True
                False
                # 3.如何获取校验之后通过的数据
                form_obj.cleaned_data
                {'username': 'yafeng'}
                # 4.如何获取校验失败及失败的原因
                form_obj.errors
                {
                 'password': ['Ensure this value has at least 3 characters (it has 2).'],
                 'email': ['Enter a valid email address.']
                 }
                # 5.注意 forms组件默认所有的字段都必须传值 也就意味着传少了是不行的 而传多了则没有任何关系 只校验类里面写的字段 多传的直接忽略了
                form_obj = views.MyRegForm({'username':'yafeng','password':'123456'})
                form_obj.is_valid()
                Out[12]: False
                form_obj.errors
                Out[18]: {'email': ['This field is required.']}
    
    
                form_obj = views.MyRegForm({'username':'yafeng','password':'123456',"email":'123@qq.com',"hobby":'hahahaha'})
                form_obj.is_valid()
                Out[14]: True
                form_obj.cleaned_data
                Out[15]: {'username': 'yafeng', 'password': '123456', 'email': '123@qq.com'}
                form_obj.errors
                Out[16]: {}

    三、forms组件之渲染标签

      首先我们还是需要先写一个类

      注意:forms组件只帮你渲染获取用户输入(输入 选择 下拉 文件)的标签不会渲染按钮以及form表单标签,渲染出来的每一个input提示信息都是类中的字段首字母大写。

    # forms渲染页面
    def reg(request):
        # 1、先生成一个空的类的对象
        form_obj = MyRegForm()
        # 2、直接将该对象传给前端页面
        return render(request, 'reg.html', locals())

    1、第一种渲染方式

      便于本地测试,但封装程度太高了,不利于扩展

      {{as_p}}

    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
        <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
        <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
    
    </head>
    <body>
    <p>第一种渲染方式 多个p标签 优点:本地测试方便 不足之处:封装程度太高了 不便于扩展</p>
    {{ form_obj.as_p }}
    #{{ form_obj.as_ul }} # 其他类型
    #{{ form_obj.as_table }} # 其他类型
    </body>
    </html>

     2、第二种渲染方式

      自己手动去书写比如

    {{ form_obj.username.label }}{{ form_obj.username }}
    <p>第二种渲染方式:优点:扩展性高, 缺点:有几个字段就得自己手写多少个,所以书写麻烦</p>
    <label for="{{ form_obj.username.id_for_label }}"></label>   <--for是用来放对应的input框的id地址--!>
    {{ form_obj.username.label }}{{ form_obj.username }}  # 点label是获取注释,不加只会是一个空白的框
    {{ form_obj.password.label }}{{ form_obj.password }}
    {{ form_obj.email.label }}{{ form_obj.email }}
    </body>
    </html>

     3、第三种渲染方式

      for循环(推荐使用)

    <p>第三种渲染方式:推荐使用</p>
    {% for form in form_obj %}
        <p>{{ form.label }}{{ form }}</p>
      <span>{{form.errors.0}}</span>
    {% endfor %}

    四、forms组件之渲染信息

       注意:数据校验你得前后端都得有 但是前端的校验弱不禁风,可有可无,而后端的校验则必须非常全面。

       那么我们应该如何取消浏览器自动帮我们校验的功能?

    针对form表单取消前端浏览器自动校验功能, 你只需要加一个参数novalidate

    <form action="" method="post" novalidate>  # 取消前端的校验

    前端:
    <form action="" method="post" novalidate>  # 取消前端的校验
        {% for form in form_obj %}
            <p>
                {{ form.label }}{{ form }}
                <span>{{ form.errors.0 }}</span>   <--直接点索引0,拿到的就是列表的提示信息--!>
            </p>
        {% endfor %}
        <input type="submit">
    </form>

    后端:

    # forms渲染页面
    def reg(request):
        # 1、先生成一个空的类的对象
        form_obj = MyRegForm()
        if request.method == 'POST':
            # 3、获取用户数据并交给forms组件检验  request.POST
            form_obj = MyRegForm(request.POST)
            # 4、获取检验结果
            if form_obj.is_valid():
                return HttpResponse('数据没问题')
            else:
                # 获取检验失败的字段和提示信息
                print(form_obj.errors)
        # 2、直接将该对象传给前端页面
        return render(request, 'reg.html', locals())

     五、forms组件常用参数

      1、label                input的提示信息

      2、error_message   自定义报错信息的提示信息

      3、required               设置字段是否可以允许为空

      4、initial       给字段设置默认值

      5、widget     控制标签的type类型及属性

      6、validator    正则校验 可写多个正则

      widget=forms.widgets.TextInput(attrs={'class':'form-control c1  c2'})
      widget=forms.widgets.PasswordInput(attrs={'class':'form-control'})

     

     2、给input框修改样式

      widget用来控制字段的type类型

    from django import forms    # 写之前需要先导入一个模块
    from django.forms import widgets
    
    # forms之校验数据
    class MyRegForm(forms.Form):
        username = forms.CharField(max_length=8, min_length=3, label='用户名',
                                   error_messages={
                                       'max_length': '用户名最长8位',
                                       'min_length': '用户名最短三位',
                                       'required': '用户名不能为空'
                                   }, required=False, initial='reba', widget=
                                   forms.widgets.TextInput(attrs={'class': 'form-control c1 c2'})
                                   )   # 限制你的用户名最大为8位数,最小为3位数
        password = forms.CharField(max_length=8, min_length=3, label='密码',
                                   widget=forms.widgets.PasswordInput)
        email = forms.EmailField(label='邮箱',error_messages={
            'required': '邮箱必填',
            'invalid': '邮箱格式不正确',
    
        })   # 限制必须为符合邮箱类型的数据

    接下来我想用widget是input框具有bootstrap样式以及使密码变成密文就得使用widget方法

     六、钩子函数

      1、两种类型

        全局钩子针对多个字段

          比如:校验两次密码是否一致

    from django import forms    # 写之前需要先导入一个模块
    from django.forms import widgets
    
    # forms之校验数据
    class MyRegForm(forms.Form):
        username = forms.CharField(max_length=8, min_length=3, label='用户名',
                                   error_messages={
                                       'max_length': '用户名最长8位',
                                       'min_length': '用户名最短三位',
                                       'required': '用户名不能为空'
                                   }, required=False, initial='reba', #widget=
                                   # forms.widgets.TextInput(attrs={'class': 'form-control c1 c2'})
                                   )   # 限制你的用户名最大为8位数,最小为3位数
        password = forms.CharField(max_length=8, min_length=3, label='密码',
                                   # widget=forms.widgets.PasswordInput
                                   )
        confirm_password = forms.CharField(max_length=8, min_length=3, label='确认密码')
        email = forms.EmailField(label='邮箱',error_messages={
            'required': '邮箱必填',
            'invalid': '邮箱格式不正确',
    
        })   # 限制必须为符合邮箱类型的数据
    
    
        # 全局钩子
        def clean(self):     # 全局钩子固定叫clean
            # 校验密码和确认密码是否一致
            password = self.cleaned_data.get('password')   # self 指代的是当前类产生的对象
            confirm_password = self.cleaned_data.get('confirm_password')
            if not password == confirm_password:
                # 展示提示信息
                self.add_error('confirm_password', '两次密码不一致')  # 你想展示到那个字段后面就放那个字段就可以啦
    
            return self.cleaned_data
    View Code

        局部钩子针对某一个字段

          例如:校验用户名中不能包含666

        # 局部钩子
        def clean_username(self):
            username = self.cleaned_data.get('username')
            if '666' in username:
                self.add_error('username', '光喊666 是不行的')
            return username         # 注意:你把什么勾出来了你就得把什么还回去

     总结:如果你想同时操作多个字段的数据你就用全局钩子,如果你想操作单个字段的数据 你就用局部钩子

    七、forms补充

      1、正则校验(除了钩子函数之外还可以使用正则校验)

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

      2、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()  # 这个是来确定到底是什么类型
        )

      3、单选下拉select

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

      4、多选select

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

      5、单选CheckBox

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

      6、多选CheckBox

    class LoginForm(forms.Form):
        ...
        hobby = forms.MultipleChoiceField(
            choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
            label="爱好",
            initial=[1, 3],
            widget=forms.widgets.CheckboxSelectMultiple()
        )
     
  • 相关阅读:
    orcale 之数据操作
    快速排序-java
    javadoc错误: 编码gbk的不可映射字符
    javaweb-url /
    javaWeb-mvc之利用c3p0写入数据库出现乱码
    java基础-jdbc——三种方式加载驱动建立连接
    老调重弹:JDBC系列之<驱动加载原理全面解析) ----转
    java基础-反射之Class.forName
    mvc-servlet---servletContext与servletConfig2
    mvc-servlet---ServletConfig与ServletContext对象详解(转载)
  • 原文地址:https://www.cnblogs.com/yafeng666/p/12189124.html
Copyright © 2020-2023  润新知