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

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框架的forms组件与一些补充的更多相关文章

  1. Django框架 之 form组件的钩子

    Django框架 之 form组件的钩子 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 3 ...

  2. Django框架 之 modelform组件

    Django框架 之 modelform组件 浏览目录 创建mldelform 添加记录 编辑记录 Django框架中的modelform组件 通过名字我们可以看出来,这个组件的功能就是把model和 ...

  3. Django框架 之 form组件

    Django框架 之 form组件 浏览目录 Form介绍 普通的登录 使用form组件 Form详情 常用字段 校验 进阶 使用Django Form流程 一.Form介绍 我们之前在HTML页面中 ...

  4. Django框架11 /form组件、modelForm组件

    Django框架11 /form组件.modelForm组件 目录 Django框架11 /form组件.modelForm组件 1. form组件介绍 2. form常用字段与插件 3. form所 ...

  5. django中的forms组件

    form介绍 用户需要向后端提交一些数据时,我们常常把这些数据放在一个form表单里,采用form标签,里面包含一些input等标签把用户的数据提交给后端. 在给后端提交数据的时候,我们常常也需要对于 ...

  6. Python的Django框架中forms表单类的使用方法详解

    用户表单是Web端的一项基本功能,大而全的Django框架中自然带有现成的基础form对象,本文就Python的Django框架中forms表单类的使用方法详解. Form表单的功能 自动生成HTML ...

  7. Django框架 之 Cookie、Session整理补充

    Django框架 之 Cookie.Session整理补充 浏览目录 Django实现的Cookie Django实现的Session 一.Django实现的Cookie 1.获取Cookie 1 2 ...

  8. [Django高级之forms组件]

    [Django高级之forms组件] forms组件之校验字段 # 第一步:定义一个类,继承forms.Form # 第二步:在类中写字段,要校验的字段,字段属性就是校验规则 # 第三步:实例化得到一 ...

  9. Python-S9—Day85-ORM项目实战之forms组件以及Modelform补充、跨域请求及应用

    01 forms组件补充1 02 forms组件补充2 03 ModelForm回顾 04 浏览器的历史 05 jsonop实现跨域请求 06 jsonop实现跨域请求2 07 jsonop实现跨域请 ...

随机推荐

  1. 【机制】js的闭包、执行上下文、作用域链

    1.从闭包说起 什么是闭包 一个函数和对其周围状态(词法环境)的引用捆绑在一起,这样的组合就是闭包. 也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域. 在 JavaScript 中,每 ...

  2. hdu 4738 Caocao's Bridges(割边)

    题目链接 用tarjan求桥上的最小权值 #include<bits/stdc++.h> #define ll long long int using namespace std; inl ...

  3. Codeforces Round #533 (Div. 2) B. Zuhair and Strings(字符串)

    #include <bits/stdc++.h> using namespace std; int main() { int n,k;cin>>n>>k; stri ...

  4. codeforces 949B :A Leapfrog in the Array 找规律

    题意: 现在给你一个n,表示有2*n-1个方格,第奇数方格上会有一个数字 1-n按顺序放.第偶数个方格上是没有数字的.变动规则是排在最后一个位置的数字,移动到它前边最近的空位 . 直到数字之间没有空位 ...

  5. POJ-3984 迷宫问题 (BFS)

    题意:有一个\(5\)X\(5\)的\(01\)图,输出从左上角走到右下角的最短路径. 题解:基础的bfs,这里困难的是如何输出这个最短路径,我们可以用一个结构体来存点和路径,我们每次向外去拓展的时候 ...

  6. Codeforces Round #656 (Div. 3) D. a-Good String (DFS)

    题意:有一个长度为\(n=2^k\)的字符串,对于某个字符\(c\),我们定义他是一个\(c-good\),如果: ​ 1.\(len=1\),并且\(s[1]=c\). ​ 2.\(len>1 ...

  7. Windows Terminal 更换主题

    1. 打开设置,是个json文件 2. 在此处获取主题配置:https://atomcorp.github.io/themes/ 3.将主题配置粘贴到schemes节点(可以增加N个) 4.配置每个命 ...

  8. Yocto项目介绍及入门 -- 嵌入师工程师必备利器

    目录 写在前面 1. Yocto项目是什么 2. Yocto项目有什么用 3. 如何快速上手Yocto项目 4. 带你通过Yocto项目编译一个自定义镜像文件 写在前面 博主目前从事BMC工作,由于公 ...

  9. PHP7.1后webshell免杀

    严格的D盾 D盾说,我是个严格的人,看到eval我就报木马,"看着像"="就是"木马,宁可错杀一千,绝不放过一个.好了,多说无益,一起看看严格的D盾是如何错杀的 ...

  10. Linux 学习笔记分享: Linux 用户组的权限: drwx------ 700权限(d 目录 ,r=4,w=2,x=1:rwx=7;---=0;---=0)

    Linux 用户组的权限: drwx------ 700权限(d 目录 ,r=4,w=2,x=1:rwx=7;---=0;---=0) 1 1 Linux 用户组的权限: drwx------ 700 ...