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

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组件

需要用到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查看符合校验规则的数据;
# 使用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 forms组件与钩子函数的更多相关文章

  1. Forms组件与钩子函数

    目录 一:Forms组件 1.案例需求: 2.前端 3.后端 二:form表单前后端动态交互 1.form组件 2.为什么数据效验非要去后端 不能在前端利用js直接完成呢? 3.举例:购物网站 三:基 ...

  2. Django学习——分页器基本使用、分页器终极用法、forms组件之校验字段、forms组件之渲染标签、forms组件全局钩子,局部钩子

    内容 1 分页器基本使用 2 分页器终极用法 3 forms组件之校验字段 1 前端 <!DOCTYPE html> <html lang="en"> &l ...

  3. Django forms组件里的ChoiceField、ModelChoiceField和ModelMutipleChoiceField的区别

    阅读简要 首先我们要明白Django forms组件里的ChoiceField.ModelChoiceField和ModelMutipleChoiceField是继承关系 ChoiceField 1. ...

  4. ajax提交文件,django测试脚本环境书写,froms组件,钩子函数

    1.在新版本中,添加app是直接在settings设置中,将INSTALLED_APPS里添加app名字, 但是他的完整写法是   'app01.apps.App01Config'  因为新版本做了优 ...

  5. django之表多对多建立方式、form组件、钩子函数 08

    目录 多对多三种创建方式 1.全自动(用ManyToManyField创建第三张表) 2.纯手写 3.半自动 form组件 引入 form组件的使用 forms组件渲染标签 form表单展示信息 fo ...

  6. python django(forms组件)

    forms组件最大的作用,就是做数据校验. 普通做法,一个一个写校验规则,没有解耦.校验规则,都在视图函数里面. 网页校验 修改urls.py,增加路径addbook from app01 impor ...

  7. django ---forms组件

    forms组件 本文目录 1 校验字段功能 2 渲染标签功能 3 渲染错误信息功能 4 组件的参数配置 5 局部钩子 6 全局钩子 回到目录 1 校验字段功能 针对一个实例:注册用户讲解. 模型:mo ...

  8. form组件类 钩子函数验证

    # 全局钩子 def clean(self): pwd = self.cleaned_data.get("password") re_pwd = self.cleaned_data ...

  9. Django forms组件的校验

    引入: from django import forms 使用方法:定义规则,例: class UserForm(forms.Form): name=forms.CharField(max_lengt ...

随机推荐

  1. vim-plug 安装 jedi-vim

    安装: Plug 'davidhalter/jedi-vim' :PlugInstall 我就在配置文件里写了一个配置项 let g:jedi#use_tabs_not_buffers = 1 进入定 ...

  2. windows 10上源码编译dlib教程 | compile dlib on windows 10

    本文首发于个人博客https://kezunlin.me/post/654a6d04/,欢迎阅读! compile dlib on windows 10 Series Part 1: compile ...

  3. jinjia2

    ansible-playbook --become --become-method=su -K copy.yml - hosts: web remote_user: ansible tasks: - ...

  4. AE 新建项目(一)(持续更新,做到哪算哪)

    开发环境 工具:Visual Studio 2012.ArcEngine10.4.1 语言:C# 开发步骤 1.打开Visual Studio 2012,选择新建项目,创建一个.NET Framewo ...

  5. 详解在Linux系统中安装JDK

    本文以在CentOS 7.6中安装JDK8为例进行安装,其他系统和版本都是大同小异的. 下载 进入Oracle官方网站的下载页面. 首先,接受许可协议,如下图: 然后,根据Linux系统的位数选择要下 ...

  6. PowerDesigner从安装到同步数据库

    前言 最近项目在如火如荼的进行着4.0版本的数据库设计工作,我们几个后端小伙伴也马不停蹄的进行着数据库的设计.使用的设计软件是PowerDesigner,这里记录一些常见的问题以备日后查看 安装 链接 ...

  7. CSS中选择器优先级与!important权重使用

    CSS中的选择器优先级与!important权重使用 .class选择器要高于标签选择器. #id选择器要高于.class选择器. 标签选择器是优先级最低的选择器. !important的属性它的权重 ...

  8. 【Java并发系列】----JUC之Lock

    显式锁 Lock 在Java 5.0之前,协调共享对象的访问时可以使用的机制只有synchronized和volatile.Java 5.0后增加了一些新的机制,但并不是一种替代内置锁的方法,而是当内 ...

  9. CCNA 之 五 路由协议 一 静态路由

    静态路由 路由选择原理 什么是路由? 就如同去某一个地方,会有很多种路线,每一条路线经都可以称之为路由: 路由器中会维护一张路由表,每一个表项都是一条路由,也就是去往某个网络的路径,然后将对应的数据包 ...

  10. js中跳转的方法

    javascript中的location.href有很多种用法,主要如下. self.location.href="/url" 当前页面打开URL页面location.href=& ...