zoukankan      html  css  js  c++  java
  • Django框架的forms组件与一些补充

    一、多对多的三种创建方式

    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)
    

    好处:

    1. 无需自己操作第三张表,全部都是由orm自动帮你创建的。

    2. 还内置了四个操作第三张表的方法:add、remove、set、clear。

    不足:

    1. 自动创建的第三张表无法扩展个修改字段,表的扩展性较差。

    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)
    

    好处:

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

    不足:

    1. 不再支持orm跨表查询,不再有正反向的概念。
    2. 也不支持add、remove、set、clear四个内置方法。

    3. 半自动(强烈推荐)

    当你的ManyToManyField只有一个参数to的情况下,orm会自动帮你创建第三张表。

    如果你加了through和through_fields,那么orm就不会自动帮你创建第三张表,但是它会在内部帮你维护关系,让你能够继续使用orm的跨表查询。

    through: 自己指定第三张关系表

    through_fields: 自己指定第三张关系表中,到底哪两个字段维护者表与表之间的多对多关系。

    顺序反了会有问题

    class Book(models.Model):
        title = models.CharField(max_length=32)
        # 多对多关系字段
        authors = models.ManyToManyField(to='Authors',through='Book2Author',through_fields=("book","authors"))  # 这两个字段是有顺序的
    
    class Authors(models.Model):
        name = models.CharField(max_length=32)
        # 多对多关系字段  等价
        # books = models.ManyToManyField(to='Book', through='Book2Author', through_fields=("authors","book"))
    
    class Book2Author(models.Model):
        book = models.ForeignKey(to='Book')
        authors = models.ForeignKey(to='Authors')
        # 该表中可以由任意多的外键字段
        # 可以扩展任意的字段
    

    好处:

    1. 可以任意的添加和修改第三张表中的字段,扩展性强。

    2. 支持orm跨表查询

    不足:

    1. 不支持四种内置方法:add、remove、set、clear。

    二、forms组件

    form表单是前端用来朝后端发送数据的标签,他需要完成以下这几件事情:

    1. 渲染标签:生成页面可用的HTML标签
    2. 校验数据:对用户提交的数据进行校验
    3. 展示信息:保留之前输入的内容

    forms组件可以将上面这三件事情更好的完成。

    1. 如何使用forms组件

    需要自己手动创建一个文件用来写forms组件,可以随意命名,比如myforms.py

    在这个文件中通过继承django中的forms模块,来新写自定义的forms组件。

    from django import forms
    # 首先需要提前写一个类用来继承Form类,然后就可以通过这个类来
    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()
    

    2. 使用forms组件校验数据

    1. 给写好的类,传字典数据(待校验的数据)实例化出一个待校验对象;
    2. obj.is_valid()查看被校验的数据是否合法;
    3. obj.errors查看不符合规则的字段及错误的理由;
    4. obj.cleaned_data查看符合校验规则的数据;
    # 使用pycharm中的python console进行测试。
    from app01 import views
    form_obj1 = views.MyForm({'username':'tbw','password':'12','email':'qq'})
    form_obj2 = views.MyForm({'username':'tbw','password':'123','email':'123@qq.com'})
    
    # 查看校验对象是否通过校验
    print(form_obj1.is_valid())
    print(form_obj2.is_valid())
    # 查看未通过校验的数据的具体错误
    print(form_obj1.errors)
    print(form_obj2.errors)
    # 查看对象中通过了校验的数据
    print(form_obj1.cleaned_data)
    print(form_obj2.cleaned_data)
    
    '''
    False
    True
    
    {'password': ['Ensure this value has at least 3 characters (it has 2).'],'email': ['Enter a valid email address.']}
    # 这里没有错误就什么都不打印
    
    {'username': 'tbw'}
    {'username': 'tbw', 'password': '123', 'email': '123@qq.com'}
    '''
    

    注意!

    1. 使用forms组件时,写好的类中定义的字段默认都是必须传值的,不能少传。
    form_obj = views.MyForm({'username':'tbw','password':'12345'})
    form_obj.is_valid()
    form_obj.errors
    
    '''
    False
    {'email': ['This field is required.']}
    '''
    
    1. forms组件只会校验forms类中定义的字段。如果你多传了,不会有任何影响。
    form_obj = views.MyForm({'username':'tbw','password':'12345','email':'123@qq.com','xxx':'嘻嘻嘻'})
    form_obj.is_valid()
    
    '''
    True
    '''
    

    3. 使用forms组件渲染标签

    步骤:

    1. 先在后端生成一个空对象
    2. 将该对象传递给HTML前端页面
    3. 前端通过这个对象渲染标签

    特点:

    forms组件只会帮你渲染获取用户输入的标签,不会帮你渲染提交按钮, 需要你自己手动添加。

    渲染标签方式1:

    {{ form_obj.as_p }}  // 里面所有标签都有
    

    渲染标签方式2:(不推荐使用,写起来比较烦,每一行都要自己写)

    {{ form_obj.username.label }}{{ form_obj.username }}  // 只有username一个标签
    {{ form_obj.password.label }}{{ form_obj.password }}
    {{ form_obj.email.label }}{{ form_obj.email }}
    

    渲染标签方式3:

    {% for form in form_obj %}
    	<p>{{ form.label }}{{ form }}</p>  <!--form 等价于你方式2中的对象点字段名-->
    {% endfor %}
    

    改变渲染标签展现的字符:给字段添加label属性

    class MyForm(forms.Form):
        username = forms.CharField(max_length=8,min_length=3,label='用户名')
        password = forms.CharField(max_length=8,min_length=3,label='密码')
        email = forms.EmailField(label='邮箱')
    

    4. 使用forms组件展示信息

    <form action="" method="post" novalidate>
        {% for forms in form_obj %}
        <p>
            {{ forms.label }}{{ forms }}
            <span>{{ forms.errors.0 }}</span>
            error里面正好是一个一个标签对应的报错信息列表
            .0 可以拿到里面的一个一个文本,
            这样既可以随便在哪个位置展示了
        </p>  <!--form 等价于你方式2中的对象点字段名-->
        {% endfor %}
        <input type="submit">
    </form>
    

    5. 校验数据参数

    数据的校验通常前后端都必须有。

    但是前端的校验可有可无,因为弱不禁风。

    后端的校验必须要有!并且必须非常的全面!

    如何告诉浏览器不在前端做校验:

    form表单中加一个novalidate参数即可
    <form action="" method="post" novalidate>
    

    5.1 报错信息修改:error_messages

    可以修改前端页面展示的报错信息,每一条数据都可以对应修改。

    username = forms.CharField(
        max_length=8,
        min_length=3,
        label='用户名',
        initial='默认值',
        error_messages={
            'max_length':'用户名最长八位',
            'min_length':'用户名最短三位',
            'required':'用户名不能为空'
        },
    )
    
    email = forms.EmailField(
        label='邮箱',
        error_messages={
            'required':'邮箱不能为空',
            'invalid':'邮箱格式错误'  # 这条显示邮箱格式错误的报错信息
        }
    )
    

    5.2 校验器:Validator

    通过不同规则校验数据的内容格式

    # 需要先导入RegexValidator模块
    from django.core.validators import RegexValidator
    validators=[
        RegexValidator(r'^[0-9]+$', '请输入数字'),
        RegexValidator(r'^159[0-9]+$', '数字必须以159开头'),
    ]
    

    5.3 给input框设置样式及属性:widget

    可以用widget修改标签的class属性或者css样式

    1. 密码password:widget=forms.widgets.PasswordInput()
    2. 单选radioSelect:widget=forms.widgets.RadioSelect()
    3. 多选Select:widget=forms.widgets.SelectMultiple()
    4. 单选checkbox:widget=forms.widgets.CheckboxInput()
    5. 多选checkbox:widget=forms.widgets.CheckboxSelectMultiple()
    password = forms.CharField(
            min_length=6,
            label="密码",
            widget=forms.widgets.PasswordInput(  ###
                attrs={'class': 'c1'}, 
                render_value=True
            )
    )
    

    5.4 input框默认值:initial

    gender = forms.fields.ChoiceField(
            choices=((1, "男"), (2, "女"), (3, "保密")),
            label="性别",
            initial=3,  ###
            widget=forms.widgets.RadioSelect()
        )
    

    5.5 控制字段是否必填:required

    email = forms.EmailField(
        label='邮箱',
        error_messages={
            'required':'邮箱不能为空',  ### 默认为True,可以为空
            'invalid':'邮箱格式错误'
        }
    )
    

    5.6 input对应的提示信息:label

    可以点label标签选中单选框

    gender = forms.fields.ChoiceField(
            choices=((1, "男"), (2, "女"), (3, "保密")),
            label="性别",  ### 
            initial=3,  
            widget=forms.widgets.RadioSelect()
        )
    

    6. 钩子函数

    在特定的时刻,抓取特定的内容。

    钩子函数是一个函数,函数体内你可以写任意的校验代码。

    他会在数据校验通过后自动调用执行。

    6.1 局部钩子

    函数名为 clean_单个字段名

    # 校验用户名中不能含有666
    def clean_username(self):
        username = self.cleaned_data.get('username')
        if '666' in username:
            # 给username所对应的框展示错误信息
            self.add_error('username','光喊666是不行的')
            # raise ValidationError('到底对不对啊')
        # 将单个数据username数据返回
        return username
    

    6.2 全局钩子

    函数名为 clean,会对cleaned_data中的所有键值对一个一个进行校验。。

    def clean(self):
        password = self.cleaned_data.get("password")
        confirm_password = self.cleaned_data.get("confirm_password")
        if not password == confirm_password:
            self.add_error('confirm_password','两次密码不一致')
        # 将全局的数据返回
        return self.cleaned_data
    
  • 相关阅读:
    Django中的CSRF
    CentOS 7上快速安装saltstack
    Django中的Form和ModelForm
    Linux下git使用
    django 登录、注册
    django 知识点小结
    django 博客搭建
    django models中字段
    django models中的class meta
    Django Queryset增加manager
  • 原文地址:https://www.cnblogs.com/bowendown/p/11979631.html
Copyright © 2011-2022 走看看