zoukankan      html  css  js  c++  java
  • 1203 forms组件

    	多对多三种创建方式
    	
    	forms校验性组件
    	
    	django settings源码
    
    

    昨日内容

    ajax结合sweetalert
    		自己写一个删除按钮的确认框
    	
    	去github上下载sweetalert源码 你只需要使用里面dist文件夹
    		gitlab
    		公司自己搭建
    		码云
    	
    	参考示例书写即可
    		
    		
    	二次开发能力
    		基于人家已经写好的功能修改
    			1.先看别人的配置参数
    			2.前期就是猜
    			3.整体修改
    	linux
    	redis
    	mongodb
    	github
    	git
    	
    	批量处理
    		bulk_create()
    		当你要批量操作数据库的时候 一定要减少走数据库的频率
    		
    	数据的分页展示
    		django其实有内置的分页模块
    		但是该模块不好用,书写麻烦,功能不健全
    		
    		自定义分页
    			1.queryset支持切片操作
    			2.研究当前页 每页展示多少条数据  起始位置 终止位置
    			3.前端代码不一定非要在前端书写  后端也可以
    		
    		把自定义的代码拷贝到本地
    			基本使用
    				将代码放入到一个py文件中
    				
    				导入该文件中的类
    				
    					1.生成该类的对象
    						展示数据的总条数
    						用户想访问的页码
    						默认参数每页展示几条数据
    						分页页码的个数 奇数位
    					
    					2.前端使用
    						qeuryset部分
    						|safe
    

    多对多三种创建方式

    封装程度越高,可扩展性越差

    1.全自动

    一般情况下

    class Book(models.Model):
        title = models.CharField(max_length=32)
        # 多对多字段
        authors = models.ManyToManyField(to='Authors')
    
    class Authors(models.Model):
        name = models.CharField(max_length=32)
    

    好处

    • 自始至终你都没有操作第三张表,全部都是有orm自动帮你创建
    • 内置了四个操作第三张表的方法
      • add
        remove
        set
        clear

    缺点

    • 自动创建的第三张表无法扩展和修改字段,表的扩展性较差

    2.纯手动

    了解

    class Book(models.Model):
        title = models.CharField(max_length=32)
    
    class Authors(models.Model):
        name = models.CharField(max_length=32)
    
    
    # 自建第三张表
    
    class Book2Authors(models.Model):
        book = models.ForeignKey(to='Book')
        author = models.ForeignKey(to='Authors')
        
        # 可以手动创建第三张表中的字段
        create_time = models.DateField(auto_now_add=True)
    

    好处

    • 第三张表中字段个数和字段名称全都可以自己定义

    缺点

    • 不再支持orm跨表查询,没有正反向的概念
    • 不能使用修改字段方法
      • add
        remove
        set
        clear

    3.半自动through='',through_fields=(外键字段)

    推荐使用

    # 半自动
    class Book(models.Model):
        title = models.CharField(max_length=32)
    
        # 多对多关系字段
        authors = models.ManyToManyField(to='Authors',through='Book2Authors',through_fields=('authors','book'))
    
    
    class Authors(models.Model):
        name = models.CharField(max_length=32)
    
    
    # 自建第三张表
    class Book2Authors(models.Model):
        book = models.ForeignKey(to='Book')
        author = models.ForeignKey(to='Authors')
        # 该表中有任意多的外键字段
        
    
    • through='第三张表名'指定了不自动创建,手动创建的第三张表名,并与之关联
    • through_fields=('','')指定了第三张表中的到底哪两个字段维护表之间多对多关系,外键在哪,哪个字段在前面
    当你的ManyToMany只有一个参数to的情况下orm会自动帮你创建第三张表
    如果你加了throug和through_fields那么orm就不会自动帮你创建第三张表,但是他会在内部帮你维护关系,让你能够继续使用orm的跨表查询
    
    through		自己制定第三张表关系
    through_fields		自己制定第三张表中到底哪两个字段维护这表与表之间的多对多关系,外键在哪个表中,参数放在前面
    

    好处

    • 可以任意的添加和修改第三张表中的字段
    • 支持orm跨表查询

    缺点

    • 不支持表字段的修改方法
    • add
      remove
      clear
      set

    forms组件

    1.简单引入

    需求:
        注册页面,获取用户输入的用户名和密码
        提交到后端之后,后端需要对用户名和密码进行校验
        用户名中不能含有'金 瓶 梅'
        密码不能少于三位
        如果不符合,展示响应的错误信息
    

    views

    from django.shortcuts import render,HttpResponse,redirect
    
    # Create your views here.
    
    
    def register(request):
        # get请求来的时候直接走的是空值字典
        errors = {'username':'','password':''}
        # 当请求方式是post时给字典赋值
        if request.method == 'POST':
            username = request.POST.get('username')
            password = request.POST.get('password')
            if '金 瓶 梅' in username:
                errors['username'] = '不符合社会主义核心价值观'
    
            if len(password) < 4:
                errors['password'] = '注意注意太少了'
        return render(request,'register.html',locals())
    

    register.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>简易校验用户的输入功能</title>
        <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
        <link rel="stylesheet" href="bootstrap-3.3.7-dist/css/bootstrap.min.css">
        <script src="bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
    
    </head>
    <body>
    
    <form action="" method="post">
        <p>username
            <input type="text" name="username">
            <span style="color: red">{{ errors.username }}</span>
        </p>
        <p>password
            <input type="text" name="password">
            <span style="color: red">{{ errors.password }}</span>
        </p>
        <input type="submit">
    </form>
    </body>
    </html>
    

    以上代码简单做到的事

    • 手动书写html代码获取用户输入 -- 渲染标签
    • 将数据传递给后端做数据校验 -- 校验数据
    • 如果有数据错误,你还展示了错误信息 -- 展示信息

    2.forms组件作用

    能够做的事情就是上面的三步

    • 渲染标签
    • 校验数据
    • 展示信息

    使用forms组件的第一步,必须先写一个类

    from django import  forms
    
    from django import  forms
    
    class MyForm(forms.Form):
        # username字段 最少三位,最多八位
        username = forms.CharField(max_length=8,min_length=3)
        # password字段 最少三位,最多八位
        password = forms.CharField(max_length=8,min_length=3)
        # email字段 必须是邮箱格式
        email = forms.EmailField()
    

    测试用pycharm

    右下角 python console
    自动创建测试环境
    

    img

    2.1 校验数据

    实例化创建的类,传入字典,字典中是需要校验的数据,获得对象form_obj

    form_obj = views.MyForm({'username':'jason','password':'12','email':'123'})
    
    

    1.is_vaild 查看是否合法

    form_obj.is_valid()
    
    False  # 只有当你的数据全部符合校验规则的情况下 结果才是True 否则都为False
    

    2..errors 查看不符合的字段及原因

    form_obj.errors
    
    {
    'password': ['Ensure this value has at least 3 characters (it has 2).'],
    'email': ['Enter a valid email address.']
    }
    

    3.cleaned_data 查看符合的数据

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

    4.传值的顺序(少传值与多传值)

    img

    forms组件中 定义的字段默认都是必须传值的 不能少传

    少传了字段会报错
    form_obj = views.MyForm({'username':'jason','password':'12345'})
    
    form_obj.is_valid()
    False
    
    form_obj.errors
    {'email': ['This field is required.']}
    
    

    forms组件只会校验forms类中定义的字段 如果你多传了 不会有任何影响

    多设置字段并不会影响
    form_obj = views.MyForm({'username':'jason','password':'12345','email':'123@qq.com','xxx':'嘿嘿嘿'})
    
    form_obj.is_valid()
    True
    

    2.2 渲染标签

    第一步需要生成一个空的forms类的对象

    class MyForm(forms.Form):
    	pass
    	
    	
    def index(request):
    	第一步需要生成一个空的forms类的对象
        form_obj = MyForm()
        直接将生成的对象传递给前端页面
        return render(request,'index.html',locals())
    
    • froms组件只会帮你渲染获取用户输入的标签 不会帮你渲染提交按钮 需要你自己手动添加

    第一种as_p as_ul as_table

    直接将所有的信息一起渲染出来

    reg.html

    Copy<!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
        <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
        <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
        <title>Title</title>
    </head>
    <body>
        <div class="container">
            <div class="row">
                {#第一种渲染方式#}
                <div class="col-md-offset-2 col-md-8">
                    <form action="" method="post">
                        {% csrf_token %}
                        {{ form.as_p }}
                        <hr>
                        {{ form.as_table }}
                        <hr>
                        {{ form.as_ul }}
                        <hr>
                        <input type="submit" value="提交" class="btn btn-success">
                    </form>
                </div>
    
            </div>
        </div>
    </body>
    </html>
    

    这种方式, Django的封装程度太高了, 我们完全不能够自定义样式, 所以它只能用来前期的页面快速搭建以及做测试使用. 最后的渲染结果巨丑无比... 实际基本不考虑它.

    img

    第二种

    单独渲染每一个标签

    <p>forms组件渲染标签方式2(不推荐使用,写起来太多)</p>
    {#input框的提示信息                 获取input框#}
    {{ form_obj.username.label }}{{ form_obj.username }}
    
    

    当我们使用form对象.字段名字的时候, 可以发现这样只渲染出单独的一个input框. 检查还能发现form组件渲染完毕后的一些规律.

    img

    第三种

    上面这种方式也有一个不好的地方, 就是当字段多了以后, 每一个都需要添加类似的样式, 就比较麻烦, 这时候就需要用到第三种方式

    遍历form对象来渲染出标签. 只需要对form对象作出以下小的变化, 就可以达到同样的效果

    {% for form in form_obj %}
        <p>{{ form.label }}{{ form }}</p>
    {% endfor %}
    

    img

    可以定义类的label默认设置来渲染出页面的标签

    class RegForm(forms.Form):
        # 接下来的定义需要与模型表的字段类型一一对应
        username = forms.CharField(
            max_length=15,  # 用户名最大长度为15
            min_length=3,  # 用户名的最小长度为3
            label='用户名',  # 渲染出在页面上的标签的名字
        )
        password = forms.CharField(
            max_length=15,  # 密码最大长度为15
            min_length=3,  # 密码的最小长度为3
            label='密码',  # 渲染出在页面上的标签的名字
        )
    

    2.3 展示信息

    告诉浏览器不做前端校验 form表单设置novalidate参数即可

    <form action="" method="post" novalidate>
    
    

    如何校验前端用户传入的数据

    展示错误信息

    views
    
    def index(request):
        # 获得空的forms类对象
        form_obj = MyForm()
        # 校验前端用户传入的数据
        if request.method == 'POST':
            # 获取用户的数据,在request.POST中,forms组件校验数据
            form_obj = MyForm(request.POST)   # 该变量名一定要与上面的变量名一致
            if form_obj.is_valid():
                print(form_obj.cleaned_data)
                return HttpResponse('数据全部')
            else:
                print(form_obj.errors)
        return render(request,'index.html',locals())
        
        
    -------------------------------------------------------
    
    index.html
    
    <form action="" method="post" novalidate>
        {% for form in form_obj %}
            <p>
                {{ form.label }}{{ form }}
    {#            form 等价于方式2中的对象点字段名(使用.0获取列表中的信心)#}
            <span>{{ form.errors.0 }}</span>
            </p>
        {% endfor %}
        <input type="submit">
    </form>
    

    img

    参数设置

    class MyForm(forms.Form):
        # username字段 最少三位,最多八位
        username = forms.CharField(max_length=8,min_length=3,label='用户名',
                                   error_messages={
                                       'max_length':'用户名最长8位',
                                       'min_length':'用户名最短3位',
                                       'required':'用户名不能为空'
                                   })
        # email字段 必须是邮箱格式
        email = forms.EmailField(label='邮箱',
                                 error_messages={
                                     'required':'邮箱不能为空',
                                     'invalid':'邮箱格式错误'
                                 })
    
    • label= 设置提示信息

    • error_messages={}设置报错信息

      • required 不能为空
      • invalid 邮箱格式
    • validations 内置校验器

      RegexValidator 正则校验

    2.4 校验数据补充

    内置的校验器

    内置的校验器   
        from django.core.validators import RegexValidator   
        	validators=[            
        	RegexValidator(r'^[0-9]+$', '请输入数字'),            
        	RegexValidator(r'^159[0-9]+$', '数字必须以159开头'),         
        	]
    

    钩子函数 HOOK

    会在普通校验全部符合后开始校验

    上面只靠类型检查明显不符合一些比较复杂的校验, 例如用户名不能包含敏感词, 两次密码需要一致, 这都需要进行校验.

    类内部的方法,是一个函数,函数体内你可以写任意的校验

    局部钩子 clean_字段值

    单独校验某一个字段的

    .add_error展示某一字段的错误信息

    最后需返回字段数据return username

    类中定义函数:
    	# 校验用户名中不能含有666
        
        def clean_username(self):
            # 校验通过的数据在 cleaned_data
            username = self.cleaned_data.get('username')
            # 第二层的判断
            if '666' in username:
                # 给username字段对应的框显示错误信息
                self.add_error('username','后面的是报错')
            # 将username数据返回
            return username
    

    全局钩子 clean

    校验多个字段之间的关系的

    return全局的数据return self.cleaned_data

    类中
    	# 校验两次密码是否一致
    	
        def clean(self):
            password = self.cleaned_data.get('password')
            re_password = self.cleaned_data.get('re_password')
            if not password == re_password:
                self.add_error('re_password','两次密码不一致')
            # 将全局的数据返回
            return self.cleaned_data
    

    补充知识点

    小猿取经博客园密码
    	xiaoyuanqujing@666
    

    其他字段及参数

    其他字段属性

    • lable 设置input对应的提示信息

    • initial 给input框设置默认值

    • required 默认为True,控制字段是否为空

    • widget 设置密码文本的显示方式

      • widget=forms.widgets.PasswordInput()

        from django.forms import widgets
        
        widget=forms.widgets.PasswordInput()
        
      • widget=forms.widgets.TextInput()

        括号内可以设置类内的属性 填写字典{},添加多个参数空格连接
        
        widget=forms.widgets.TextInput({'class':'form-control c1 c2','username':'jack'})
        

    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.ChoiceField(
            choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),
            label="爱好",
            initial=3,
            widget=forms.widgets.Select()
        )
    
    

    多选Select

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

    单选checkbox

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

    多选checkbox

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

    choice字段注意事项

    在使用选择标签时,需要注意choices的选项可以配置从数据库中获取,但是由于是静态字段 获取的值无法实时更新,需要重写构造方法从而实现choice实时更新。

    方式一:

    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())  # 单选
    
  • 相关阅读:
    MyGame--java语言编写的打飞机游戏(附源码下载)
    调用MyFocus库,简单实现二十几种轮播效果
    aBowman >>可以运用到自己博客上的小插件
    css通用小笔记03——浏览器窗口变小 div错位的问题
    css通用小笔记02——浮动、清除(三个例子)
    css通用小笔记01——导航背景
    PHP强制转换类型
    数据库---查询语句(三):高级查询
    数据库---T-SQL语句:查询语句(二)
    数据库---T-SQL语句(一)
  • 原文地址:https://www.cnblogs.com/fwzzz/p/11979360.html
Copyright © 2011-2022 走看看