Django --- 多对多关系创建,forms组件

多对多三种创建方式

1.系统直接创建

在创建表的时候让系统来创建第三张表,

优点:

1.可以使用可以使用系统自带的增删改查

2.不用再手动去创建表

缺点:

1.创建出来的表没有办法进行修改,可扩展性太差了

authers = models.ManyToManyField(to='Auther')

2.自己手动创建

可以根据自己的需求来创建第三张表,创建表的时候最好时候一对多关系,对表中的数据进行约束,保证数据的可靠性。

优点:

1.创建出来的表可以按照自己的使用来进行修改

2.可扩展性高

缺点:

1.没有办法使用多表操作,可以使用一对多,一对一的方式来进行修改

2.不支持跨表查询

class AutherBook(models.Model):
    auther = models.ForeignKey(to='Auther') 
    book = models.ForeignKey(to='Book')

3.自己定义加与系统创建

先自己定义一张表,然后将系统定义的表指向自己定的表。

优点:

1.可以修改表中的字段

2.支持跨表查询

缺点:

1.不支持多表操作

authers = models.ManyToManyField(to='Auther',through='AutherBook',through_fields=('book','authers'))

# through  指定自己创建的第三张表
# theough_fields   指定第三张表中与之关联的字段,有顺序要求,定义的外键字段在谁那里,就先写谁


forms组件

forms组件的主要功能:

1.可以生成可用的HTML标签

2.对用户提交的数据进行校验

3.保留上次输入内容

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

1. 如何使用forms组件

需要用到django中的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查看符合校验规则的数据;

注意!

  1. 使用forms组件时,写好的类中定义的字段默认都是必须传值的,不能少传。
  2. forms组件只会校验forms类中定义的字段。如果你多传了,不会有任何影响。

3. 使用forms组件渲染标签

特点:

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

渲染标签方式1:

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

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

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

渲染标签方式3:(推荐使用,使用的时候记得加提交按钮)

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

改变渲染标签展现的字符:给字段添加label属性,在显示的时候显示的是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 正则校验器:RegexValidator

通过正则匹配校验数据的内容格式

# 需要先导入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

原文地址:https://www.cnblogs.com/whkzm/p/11980639.html