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

当你觉得上面的所有的校验还不能够满足你的需求 你可以考虑使用钩子函数

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

局部钩子

你想校验单个字段

全局钩子

你想校验多个字段

Hook函数实例

Django多对多关系建立及Form组件的更多相关文章

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

    目录 多对多三种创建方式 1.系统直接创建 2.自己手动创建 3.自己定义加与系统创建 forms组件 1. 如何使用forms组件 2. 使用forms组件校验数据 3. 使用forms组件渲染标签 ...

  2. django -- 多对多关系的实现

    在django中表和表之间的多对多关系有两种实现方案: 方案一:直接使用django自动实现的多对多关系. 方案二:自己写连接表.然而告诉django在实现多对多关系时要使用的连接表. 一.方案一: ...

  3. 【Django入坑之路】Form组件

    1:From组件的简单使用 1创建From: #导入模块 from django import forms from django.forms import fields, widgets # 导入自 ...

  4. Django 多对多 关系

    多对多,本意就是多个一对多的关系 定义多对多 ManyToManyField 字段 from django.db import models # 学生类 class Student(models.Mo ...

  5. django多对多数据库建立 以及数据的传输 并进行增加 删除 修改

    多对多数据库的建立 class Host(models.Model): nid = models.AutoField(primary_key=True) #自增id hostname = models ...

  6. django 学习-10 Django多对多关系模型

    1.vim blog/models.py class   Author(models.Model): name = models.CharField(max_length=30) def unicod ...

  7. 六、hibernate表与表之间的关系(多对多关系)

    多对多关系 创建实体类和对应映射文件 Student.java package com.qf.entity; import java.util.HashSet; import java.util.Se ...

  8. django之分页器、多对多关系、form校验组件

    批量插入数据 bulk_create # 1.往书籍表中插入数据 1000 # for i in range(1000): # 这种插入方式 效率极低 # models.Book.objects.cr ...

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

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

随机推荐

  1. Python测试框架对比

    如有任何学习问题,可以添加作者微信:lockingfree 更多学习资料请加QQ群: 822601020获取 unittest, pytest, nose, robot framework对比 什么是 ...

  2. tez 0.9.0 配置

    官网: https://tez.apache.org/releases/0.9.0/tez-api-javadocs/configs/TezConfiguration.html

  3. 【2018.08.01】(表/栈/队列/大小顶堆)学习Stark和Queue算法小记

    Train Problem I As the new term comes, the Ignatius Train Station is very busy nowadays. A lot of st ...

  4. GO 类型断言

    在Go语言中,我们可以使用type switch语句查询接口变量的真实数据类型,语法如下: switch x.(type) { // cases } x必须是接口类型. 来看一个详细的示例: type ...

  5. 深入了解JVM虚拟机8:Java的编译期优化与运行期优化

    java编译期优化 java语言的编译期其实是一段不确定的操作过程,因为它可以分为三类编译过程:1.前端编译:把.java文件转变为.class文件2.后端编译:把字节码转变为机器码3.静态提前编译: ...

  6. Factor_Analysis

    Factor_Analysis(因子分析) Factor Analysis 简书:较好理解的解释,其中公式有一定的推导(仅展现关键步骤,细节大多需要自行补充),基本为结论式. 感性层面理解:首先,明确 ...

  7. 软阈值迭代算法(ISTA)和快速软阈值迭代算法(FISTA)

    缺月挂疏桐,漏断人初静. 谁见幽人独往来,缥缈孤鸿影. 惊起却回头,有恨无人省. 拣尽寒枝不肯栖,寂寞沙洲冷.---- 苏轼 更多精彩内容请关注微信公众号 "优化与算法" ISTA ...

  8. Dubbo 2.6.0升级到2.7.3

    dubbo依赖,修改groupId和升级version版本号 <dependency> <groupId>com.alibaba</groupId> <art ...

  9. H2O框架简介

    H2O框架简介H2O是开源的,分布式的,基于内存的,可扩展的机器学习和预测分析框架,适合在企业环境中构建大规模机器学习模型. H2O核心代码使用Java编写,数据和模型通过分布式 Key/Value ...

  10. jeecg使用心得

    接触到jeecg框架是在去年,接触到了jeecg开源框架,此框架为企业级急速开发框架,不了解的可以百度下这类框架的,对于目前状态来说,此框架确实也满足了所需,此刻就开始接触jeecg框架,去年六七月份 ...