Django多对多关系建立及Form组件
Django多对多关系
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.半自动(推荐使用)
class Book(models.Model):
title = models.CharField(max_length=32)
# 多对多关系字段
authors = models.ManyToManyField(to='Authors',through='Book2Author',through_fields=("book","authors"))
# 不通过orm创建,而是通过第三张表中->through='Book2Author'的through_fields=("authors","book"),authors和book字段
# through_fields=("authors","book")中的"authors"字段,可以这样记:在哪张表里面该字段就放在最前面
"""
当你的ManyToManyField只有一个参数to的情况下 orm会自动帮你创建第三张表
如果你加了through和through_fields那么orm就不会自动帮你创建第三张表 但是它会在内部帮你维护关系 让你能够继续使用orm的跨表查询
through 自己指定第三张关系表
through_fields 自己指定第三张关系表中 到底哪两个字段维护者表与表之间的多对多关系
"""
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')
- 不通过orm创建,而是通过第三张表中->through='Book2Author'的through_fields=("authors","book"),authors和book字段
- through_fields=("authors","book")中的"authors"字段,可以这样记:在哪张表里面该字段就放在最前面
- 该表可以有任意多的外键字段
- 可以扩展任意的字段
好处:可以任意的添加和修改第三张表中的字段
并且支持orm跨表查询
不足:不支持
add
remove
set
clear
forms校验组件
forms组件
前戏
需求:
1.写一个注册页面 获取用户输入的用户名和密码
提交到后端之后 后端需要对用户名和密码做校验
用户名里面不能含有葫芦娃
密码不能少于三位
如果不符合 展示对应的错误信息
forms组件 能够做的事情
1.手动书写html代码获取用户输入 >> >> >> 渲染标签
2.将数据转递给后端做数据校验 >> >> >> 校验数据
3.如果数据有错误 你还展示了错误信息 >> >> >> 展示信息
使用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()
校验数据
# 1.给写好的类 传字典数据(待校验的数据)
form_obj = views.MyForm({'username':'jason','password':'12','email':'123'})
# 2.如何查看校验的数据是否合法
form_obj.is_valid()
False # 只有当你的数据全部符合校验规则的情况下 结果才是True 否则都为False
# 3.如何查看不符合规则的字段及错误的理由
form_obj.errors
{
'password': ['Ensure this value has at least 3 characters (it has 2).'],
'email': ['Enter a valid email address.']
}
# 4.如何查看符合校验规则的数据
form_obj.cleaned_data
{'username': 'jason'}
# 5.forms组件中 定义的字段默认都是必须传值的 不能少传
form_obj = views.MyForm({'username':'jason','password':'12345'})
form_obj.is_valid()
False
form_obj.errors
{'email': ['This field is required.']}
# 6.forms组件只会校验forms类中定义的字段 如果你多传了 不会有任何影响
form_obj = views.MyForm({'username':'jason','password':'12345','email':'123@qq.com','xxx':'嘿嘿嘿'})
form_obj.is_valid()
True
渲染标签
forms组件只会帮你渲染获取用户输入的标签 不会帮你渲染提交按钮 需要你自己手动添加
<p>forms组件渲染标签方式1:封装程度态高 不推荐使用 但是可以用在本地测试</p>
{{ form_obj.as_p }} <!--自动渲染所有input框 -->
{{ form_obj.as_ul }}
{{ form_obj.as_table }}
<p>forms组件渲染标签方式2:不推荐使用 写起来太烦了</p>
{{ form_obj.username.label }}{{ form_obj.username }}
{{ form_obj.username.label }}{{ form_obj.password }}
{{ form_obj.username.label }}{{ form_obj.email }}
<p>forms组件渲染标签方式3:推荐使用 </p>
{% for form in form_obj %}
<p>{{ form.label }}{{ form }}</p> <!--form 等价于你方式2中的对象点字段名-->
{% endfor %}
展示信息
<p>forms组件渲染标签方式3:推荐使用 </p>
<form action="" method="post" novalidate>
{% for forms in form_obj %}
<p>
{{ forms.label }}{{ forms }}
<span>{{ forms.errors.0 }}</span>
</p> <!--form 等价于你方式2中的对象点字段名-->
{% endfor %}
<input type="submit">
</form>
使用forms组件实现注册功能
先定义好一个ReGForm类:
from django import forms
# 按照Django form组件的要求自己写一个类
class RegForm(forms.Form):
name = forms.CharField(label="用户名")
pwd = forms.CharField(label="密码")
再写一个视图函数
# 使用form组件实现注册方式
def register2(request):
form_obj = RegForm()
if request.method == "POST":
# 实例化form对象的时候,把post提交过来的数据直接传进去
form_obj = RegForm(request.POST)
# 调用form_obj校验数据的方法
if form_obj.is_valid():
return HttpResponse("注册成功")
return render(request, "register2.html", {"form_obj": form_obj})
login.htmll
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>注册2</title>
</head>
<body>
<form action="/reg2/" method="post" novalidate autocomplete="off">
{% csrf_token %}
<div>
<label for="{{ form_obj.name.id_for_label }}">{{ form_obj.name.label }}</label>
{{ form_obj.name }} {{ form_obj.name.errors.0 }}
</div>
<div>
<label for="{{ form_obj.pwd.id_for_label }}">{{ form_obj.pwd.label }}</label>
{{ form_obj.pwd }} {{ form_obj.pwd.errors.0 }}
</div>
<div>
<input type="submit" class="btn btn-success" value="注册">
</div>
</form>
</body>
</html>
看网页效果发现也验证了form的功能:
前端页面是form类的对象生成的——>生成HTML标签功能
当用户名和密码输入为空或输错之后 页面都会提示——>用户提交校验功能
当用户输错之后再次输入上次的内容还保留在input框中——>保留上次输入内容
form常用字段和插件
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()
)
数据校验
数据的校验通常前后端都必须有
但是前端的校验可有可无 并且弱不禁风
后端的校验必须要有 并且必须非常的全面
如何告诉浏览器不做校验 form表单中加一个novalidate
参数即可
<form action="" method="post" novalidate>
内置的校验器
from django.core.validators import RegexValidator
validators=[
RegexValidator(r'^[0-9]+$', '请输入数字'),
RegexValidator(r'^159[0-9]+$', '数字必须以159开头'),
]
钩子函数 HOOK
当你觉得上面的所有的校验还不能够满足你的需求 你可以考虑使用钩子函数
是一个函数 函数体内你可以写任意的校验代码
局部钩子
你想校验单个字段
全局钩子
你想校验多个字段
Django多对多关系建立及Form组件的更多相关文章
- Django --- 多对多关系创建,forms组件
目录 多对多三种创建方式 1.系统直接创建 2.自己手动创建 3.自己定义加与系统创建 forms组件 1. 如何使用forms组件 2. 使用forms组件校验数据 3. 使用forms组件渲染标签 ...
- django -- 多对多关系的实现
在django中表和表之间的多对多关系有两种实现方案: 方案一:直接使用django自动实现的多对多关系. 方案二:自己写连接表.然而告诉django在实现多对多关系时要使用的连接表. 一.方案一: ...
- 【Django入坑之路】Form组件
1:From组件的简单使用 1创建From: #导入模块 from django import forms from django.forms import fields, widgets # 导入自 ...
- Django 多对多 关系
多对多,本意就是多个一对多的关系 定义多对多 ManyToManyField 字段 from django.db import models # 学生类 class Student(models.Mo ...
- django多对多数据库建立 以及数据的传输 并进行增加 删除 修改
多对多数据库的建立 class Host(models.Model): nid = models.AutoField(primary_key=True) #自增id hostname = models ...
- django 学习-10 Django多对多关系模型
1.vim blog/models.py class Author(models.Model): name = models.CharField(max_length=30) def unicod ...
- 六、hibernate表与表之间的关系(多对多关系)
多对多关系 创建实体类和对应映射文件 Student.java package com.qf.entity; import java.util.HashSet; import java.util.Se ...
- django之分页器、多对多关系、form校验组件
批量插入数据 bulk_create # 1.往书籍表中插入数据 1000 # for i in range(1000): # 这种插入方式 效率极低 # models.Book.objects.cr ...
- django之表多对多建立方式、form组件、钩子函数 08
目录 多对多三种创建方式 1.全自动(用ManyToManyField创建第三张表) 2.纯手写 3.半自动 form组件 引入 form组件的使用 forms组件渲染标签 form表单展示信息 fo ...
随机推荐
- Hadoop(1)---运行Hadoop自带的wordcount出错问题。
在hadoop2.9.0版本中,对namenode.yarn做了ha,随后在某一台namenode节点上运行自带的wordcount程序出现偶发性的错误(有时成功,有时失败),错误信息如下: // : ...
- SpringCloud介绍及入门(二)
接口的实现 在user_service_interface中添加一个User的类. 增加私有属性 id,name , 并利用快捷键Alt+Insert 实现get,set的快速生成. 实体类User ...
- Java 代码里乱打日志了,这才是正确的打日志姿势
使用slf4j 使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一. 实现方式统一使用: Logback框架 打日志的正确方式 什么时候应该打日志 当你遇到问题的时候,只能通过debug功能 ...
- 【Canvas】勾画调和级数Harmonic series 曲线 y=1+1/2+1/3+1/4+1/5+1/6+1/7+1/8+....
相关资料:https://baike.baidu.com/item/%E8%B0%83%E5%92%8C%E7%BA%A7%E6%95%B0/8019971?fr=aladdin 调和级数(英语:Ha ...
- LC 991. Broken Calculator
On a broken calculator that has a number showing on its display, we can perform two operations: Doub ...
- 【分类算法】决策树(Decision Tree)
(注:本篇博文是对<统计学习方法>中决策树一章的归纳总结,下列的一些文字和图例均引自此书~) 决策树(decision tree)属于分类/回归方法.其具有可读性.可解释性.分类速度快等优 ...
- Foxmail找回密码 及 Wireshark 使用【我】
Foxmail中设置了密码,但是时间长忘了,现在要用,需要弄出来 首先,安装 Wireshark 抓包工具 一路下一步即可, 安装完确保这个图标表示的组件已经安装: 如果没有安装,在Wireshark ...
- QSplitter的使用案例
#include <QApplication> #include <QSplitter> #include <QTextEdit> #include <QTe ...
- KDChart example
/******************************************************************************** ** Form generated ...
- 简单模拟 Promise
class promise { constructor(fn) { this.data = null; this.err = null; this.isPromise = false; this.er ...